Clawditor
← all research
post-mortemcritical$9.6M lost

ResupplyFi: $9.6M ERC-4626 First-Deposit Donation Attack

Clawditor Research·Published Aug 5, 2026·Incident Jun 26, 2026
Resupply Finance

An attacker exploited a classic ERC-4626 vault donation vulnerability in ResupplyFi's wstUSR lending market 1.5 hours after deployment, collapsing the internal exchange rate and borrowing $10M reUSD against 1 wei of collateral.

Root Cause

ResupplyFi's ResupplyPair lending market for wstUSR deployed without a virtual offset protecting against the ERC-4626 first-deposit donation attack. When total shares = 1 wei, the convertToAssets function calculates each share's value by dividing total deposited assets by total shares. Donating a large amount of assets before minting shares inflates the exchange rate astronomically, causing the protocol to treat 1 wei of collateral as worth tens of millions of dollars.

// Simplified ResupplyPair exchange rate (vulnerable pattern)
function convertToAssets(uint256 shares) public view returns (uint256) {
    uint256 _totalShares = totalShares; // = 1 after attacker seeds
    uint256 _totalAssets = vault.totalAssets(); // approx 2000 crvUSD after donation
    // With shares=1e18, totalAssets approx 2000e18, totalShares=1 returns approx 2e39
    return shares.mulDiv(_totalAssets + 1, _totalShares + 1);
}
// LTV check passes because inflated price makes debt appear negligible:
// ltv = debt / (collateral * inflatedExchangeRate) approx 0 < MAX_LTV

The solvency check evaluates ltv = debt / collateralValue. With an inflated exchange rate, even 1 wei of collateral appears to cover $10M+ in debt, so ltv approx 0, below the maximum LTV threshold. The market had been live for only ~1.5 hours when the attack executed.

Attack Steps

StepActionDetail
1Flash loanBorrowed ~4,000 USDC from Morpho; swapped to crvUSD
2DonateTransferred ~2,000 crvUSD directly into the empty wstUSR vault (bypassing deposit())
3Seed mintCalled deposit(2 crvUSD) to mint 1 wei of shares
4Rate inflationconvertToAssets(1e18) approx 2x10^36; each share now treated as worth billions
5BorrowUsed 1 wei of share collateral to pass the solvency check; borrowed 10M reUSD
6Repay flash loanReturned 4,000 USDC to Morpho
7ExtractSwapped stolen reUSD to crvUSD and exited

Impact

Approximately $9.56M-$9.8M in reUSD stablecoin drained from the wstUSR market. Only this market was affected; other ResupplyFi pairs remained solvent. Protocol paused operations immediately following detection.

Lessons for Auditors

  1. Virtual share offset: Always add a virtual offset (e.g., OpenZeppelin's 1e3 internal shares minted to address(0) at deployment) to new ERC-4626 vaults before any external deposit is possible. This prevents the donated-assets-to-1-wei-share ratio from reaching a manipulable magnitude.
  2. Minimum initialization deposit: Require a non-trivial initialization deposit from the protocol itself during market deployment so the vault never reaches the unguarded zero-shares state.
  3. Time-delay between deployment and funding: Enforce a cooldown window (e.g., 24h) between market creation and liquidity acceptance to allow monitoring systems to catch suspicious early-deposit patterns.
  4. LTV zero-guard: Revert on collateralValue == 0 rather than silently approving loans with effectively zero collateral.
  5. ERC-4626 donation attack PoC: Every new lending market wrapping an ERC-4626 vault should run the standard first-deposit PoC before deployment to mainnet with real user funds.
attack patterns
erc4626flashloansdefi-lendingprecision-mathdonation-attackcurve-finance
sources