The $9.56 million Resupply Protocol exploit on June 26, 2025, exposed a critical class of vulnerabilities in ERC-4626 vault implementations that every DeFi developer must understand. With Bitcoin at $106,960 and Ethereum at $2,416, the economic incentives for attacking DeFi protocols have never been higher, and the Resupply attack demonstrates how a single integer division flaw can bypass all other security measures. This advanced tutorial walks through the technical details of the vulnerability and provides a comprehensive audit framework for securing ERC-4626 vault contracts.
The Objective
This tutorial aims to equip experienced Solidity developers with a systematic approach to auditing ERC-4626 vault implementations, with specific focus on exchange rate manipulation, donation attacks, and integer division vulnerabilities. By the end, you will understand exactly how the Resupply exploit worked, how to identify similar vulnerabilities in your own contracts, and how to implement robust protections that prevent this entire class of attacks.
Prerequisites
This tutorial assumes familiarity with Solidity development, the ERC-4626 tokenized vault standard, DeFi lending protocol architecture, and basic understanding of oracle price feeds. You should have experience with Foundry or Hardhat testing frameworks and understand how flash loans enable atomic transaction exploitation. Review OpenZeppelin’s ERC4626 implementation as a reference for secure vault patterns before proceeding.
Step-by-Step Walkthrough
Step 1: Understanding the Attack Vector. The Resupply attack exploited an ERC-4626 first donation vulnerability. When a vault is deployed with zero or near-zero liquidity, the first depositor gains outsized control over the vault’s price-per-share calculation. The attacker donated 2,000 crvUSD directly to the empty cvcrvUSD vault contract, then deposited 2 crvUSD to mint exactly 1 wei of shares. Because the vault held 2,000+ crvUSD but only 1 wei of shares existed, the price-per-share became astronomically inflated — the oracle reported a value of 2,000,000,000,000,000,001,998,001,998,001,998 for that single wei of collateral.
Step 2: The Integer Division Flaw. The critical vulnerability occurred at ResupplyPairCore.sol:573: _exchangeRate = 1e36 / IOracle(_exchangeRateInfo.oracle).getPrices(address(collateral)). In Solidity, integer division always rounds down toward zero. When the oracle returns an extremely large price value, dividing 1e36 by that value produces zero. This is not a bug in the Solidity language — it is documented behavior that developers must account for. The exchange rate of zero then propagated into the solvency check at line 282, where the loan-to-value calculation became: (_borrowerAmount * 0 * LTV_PRECISION) / EXCHANGE_PRECISION / _collateralAmount = 0. Since 0 <= _maxLTV always evaluates to true, the protocol accepted any borrow amount against any collateral.
Step 3: Implementing Virtual Shares. The standard mitigation for donation attacks involves implementing virtual shares and virtual assets in the vault's conversion calculations. OpenZeppelin's ERC4626 implementation adds decimal offset parameters during initialization: the vault pretends it already holds a baseline number of assets and shares, preventing the first real depositor from controlling the entire price-per-share calculation. In practice, this means adding constants to both the numerator and denominator during share-to-asset conversion, ensuring that no donation — regardless of size — can produce the extreme price inflation that enabled the Resupply attack.
Step 4: Exchange Rate Validation. Every exchange rate calculation must include explicit zero checks and reasonable bounds validation. Add require statements that enforce minimum and maximum exchange rates: require(_exchangeRate > 0, "Exchange rate underflow"); require(_exchangeRate <= MAX_RATE, "Exchange rate overflow"). Additionally, implement rate change detection that pauses operations if the exchange rate moves more than a defined percentage between consecutive blocks, catching manipulation attempts before they can be exploited.
Step 5: Liquidity Requirements. Never deploy vaults with zero liquidity. Implement initialization functions that require a minimum deposit during contract construction, and enforce minimum liquidity thresholds that prevent the vault from returning to an exploitable state. Time-locked withdrawals for large positions can prevent attackers from draining liquidity to create an empty-vault condition before executing a donation attack.
Troubleshooting
If your vault already uses virtual shares but you suspect vulnerability, audit the specific constants used. Virtual offsets that are too small relative to expected deposit sizes may not provide adequate protection. Test with adversarial scenarios: deploy the vault, have one account donate a large amount directly to the contract, then attempt to mint shares and observe the resulting price-per-share. If a single donation can change the exchange rate by more than a few percentage points, your virtual share constants need adjustment.
For protocols that accept external ERC-4626 vaults as collateral — as Resupply did — implement additional validation layers. Check the target vault's total supply and total assets before accepting it as collateral. Reject vaults with liquidity below a defined threshold. Monitor the vault's exchange rate over time and reject collateral from vaults exhibiting unusual rate changes that could indicate ongoing manipulation.
Mastering the Skill
Securing ERC-4626 vaults requires moving beyond basic contract auditing to understanding the mathematical properties of integer arithmetic under adversarial conditions. The Resupply exploit was not a complex vulnerability — it was a simple division operation that produced an unexpected result under extreme input conditions. Mastering vault security means systematically identifying every point where external input feeds into mathematical operations, understanding the range of possible inputs including adversarial extremes, and implementing guards that handle the full spectrum gracefully. The $9.56 million lost on June 26, 2025, serves as a costly reminder that in DeFi security, the edge cases are the attack vectors.
Disclaimer: This article is for educational purposes only and does not constitute financial or investment advice. Security auditing is an ongoing process, and no framework can guarantee complete protection against all vulnerabilities.
the $9.56M Resupply exploit from an integer division bug. one line of code, millions gone. this is why formal verification needs to be standard for vault contracts
audit_bro_ the integer division bug was in the exchange rate calc. standard openzeppelin would have caught it in a basic invariant test
Real yield protocols are separating from the Ponzi-nomics era
Cross-chain DeFi is the next frontier
DeFi yields are finally sustainable without token emissions
leveraged_long real yield is great but this exploit shows the implementation risk. the ERC-4626 standard itself is fine, its the edge cases that kill you
formal verification is expensive and slow. most vault devs will skip it until insurance mandates it, then it becomes standard overnight