# ERC721WrapperBase::getQuote should not take the mid-point price during transfers on liquidation

ERC721WrapperBase.getQuote returns mid-point price during controlCollateral transfers, leaving dust collateral that blocks bad-debt socialization in Euler vaults.

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

**Target:** ERC721WrapperBase oracle adapter / Euler vault liquidation
**Root cause:** getQuote branches on evc.isControlCollateralInProgress() and returns the oracle mid-point price instead of the bid price, so collateral is valued higher during the liquidation transfer than during the pre-transfer balance check.
**Steps:**
1. Violator has ERC721WrapperBase collateral and debt in an Euler vault; debt value exceeds collateral value.
2. Liquidation.sol computes collateralValue via oracle.getQuote(collateralBalance,...) using bid price (controlCollateral not in progress).
3. Liquidator calls enforceCollateralTransfer -> evc.controlCollateral, setting isControlCollateralInProgress=true.
4. During transfer, ERC721WrapperBase.getQuote returns mid-point price (higher than bid), so balanceOf/valuation is inflated.
5. checkNoCollateral sees residual dust balance > 0, returns false, socialization branch skipped.
**How found:** Read getQuote's branch on isControlCollateralInProgress, traced EVC controlCollateral callers to enforceCollateralTransfer during liquidation, then cross-referenced Euler Liquidation.sol's collateralBalance query and checkNoCollateral socialization gate to spot the price inconsistency between pre-check and transfer.
**Exploitation:** Liquidator attempts to seize full collateral of an underwater violator; because the wrapper quotes mid-point during controlCollateral, a dust remainder persists and the Euler vault's debt socialization path (Liquidation.sol#L220-L226) is never triggered, leaving unbacked debt stuck.
**Insight:** When an oracle adapter branches on transient EVC/controller state flags, compare the price used in the pre-liquidation balance check against the price used inside controlCollateral; any divergence leaves dust that defeats checkNoCollateral-style zero-balance gates.
