# Yield Theft via Permissionless Pool Creation Using Existing Vault Wrappers

Permissionless pool creation let attacker use a victim's yield-bearing vault wrapper as pool token, so the harvest hook donated the victim's yield to the attacker's pool.

- Payout: Contest reward
- Severity: high
- Program: VII Finance
- Credited: 0xHex
- Disclosed: 2026-03-07
- Write-up quality: 8/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_vii_finance_jan2026.pdf#3.1.4
- Library page: https://bugbountylibrary.com/r/cantina%3Avii_finance_jan2026%3A3.1.4
- Tags: domain:web3 impact:funds-loss kind:contest platform:cantina sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:business-logic vuln:reward-distribution

**Target:** ERC4626VaultWrapperFactory / YieldHarvestingHook Uniswap v4 pool
**Root cause:** createERC4626VaultToTokenPool accepts any assetB including existing vault wrappers, and harvest() only checks the caller is the hook, not which pool the yield is donated to.
**Steps:**
1. Identify a vault wrapper with accumulated pending yield.
2. Call `createERC4626VaultToTokenPool(attackerVault, victimWrapper, 3000, 60, SQRT_PRICE_1_1)` with attacker-controlled underlyingVaultA and victim wrapper as assetB.
3. Add minimal liquidity to the new pool via modifyLiquidity.
4. Perform a tiny swap on the attacker pool to trigger `harvestAndDistributeYield`.
5. Hook calls `_getPendingYield` on victim wrapper, `poolManager.donate` to attacker pool, then `harvest(poolManager)` mints yield tokens.
6. Remove liquidity to collect stolen yield as fees.
**How found:** Code review of the factory's createERC4626VaultToTokenPool noticed assetB had no validation, and reading the harvestAndDistributeYield modifier showed harvest() lacks pool-binding checks, so any pool containing a victim wrapper would harvest its yield.
**Exploitation:** Attacker needs no capital beyond minimal liquidity; creates a pool pairing their own mock ERC4626 wrapper with the victim's yield-bearing wrapper, triggers a swap so the hook harvests and donates the victim's pending yield to the attacker's pool, then withdraws liquidity to claim it as fees.
**Insight:** When a hook harvests yield based on pool currencies, check whether pool creation is permissionless and whether the harvest target is bound to the legitimate pool; any token with pendingYield() can be dragged into an attacker pool.
