# V3Vault.sol permit signature does not check receiving token address is USDC

V3Vault's permit2.permitTransferFrom calls never verify the permitted token is USDC, letting a liquidator repay with any worthless ERC20 and drain vault USDC.

- Payout: Contest reward
- Severity: high
- Program: Revert Lend
- Credited: VAD37
- Disclosed: 2024-05-22
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-03-revert-lend-findings/issues/368
- Library page: https://bugbountylibrary.com/r/c4%3A2024-03-revert-lend%3AH-01
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic

**Target:** V3Vault.sol permit2.permitTransferFrom liquidation repayment path
**Root cause:** The decoded PermitTransferFrom.permitted.token is passed straight to permit2.permitTransferFrom without checking it equals the vault asset (USDC); Permit2 only validates the signature, not the token's value.
**Steps:**
1. Obtain any ERC20 token with negligible value and approve Permit2.
2. Craft a PermitTransferFrom with permitted.token = worthlessToken, amount = liquidatorCost, sign it.
3. Call the vault liquidation/repay function with permitData encoding that permit and signature.
4. Vault accepts the worthless token transfer as repayment of liquidatorCost in USDC, leaving the debt settled without real USDC received.
**How found:** Code review of the three permit2.permitTransferFrom call sites, noticing the decoded permit struct's token field is never compared against the vault asset.
**Exploitation:** Attacker repays a liquidation debt using a permit signature over a worthless ERC20 instead of USDC; the vault credits the transfer as USDC, so the attacker keeps the USDC and drains it from the vault.
**Insight:** When integrating Permit2 signature transfers, the signed struct carries the token address; always assert permitted.token == expected asset, since Permit2 validates only the signature, not which token is economically valuable.
