The ResupplyFi Hack: The Audit Habit That Would Catch It

The Audit Habit That Would Have Caught Resupplyfi’s $9.6m Bug: The Auditor’s Take

May 13

| 5 min read

The Audit Habit That Would Have Caught Resupplyfi’s $9.6m Bug: The Auditor’s Take

In June 2025, ResupplyFi’s wstUSR lending market lost $9.6 million in a single transaction. One division operation rounded down to zero at a boundary the solvency check did not anticipate.

The check read the zero as “this borrower is well within their loan-to-value ceiling,” and the attacker borrowed the full pool against 1 wei of collateral. The bug class is an ERC-4626 inflation attack, well-documented and discussed in EIP-4626 itself. What makes the case worth walking through is how easy the flow was to miss in manual review. 

TL;DR

  • The ResupplyFi hack resulted in ~$9.6M drained after an attacker manipulated an effectively empty ERC-4626 vault, causing a solvency-critical exchange-rate calculation to round down to zero.
  • The zero rate did not halt borrowing. It caused the downstream loan-to-value check to evaluate the attacker as safely collateralized. 
  • Boundary-condition reasoning asks what protocol arithmetic produces when adversarial inputs push calculations to their extremes. 
  • Exchange-rate arithmetic and solvency invariants should be treated as critical attack surfaces requiring explicit boundary analysis. 

Why empty vaults are dangerous

ResupplyFi prices borrower collateral by querying an ERC-4626 vault’s convertToAssets() function. When that vault is freshly deployed and holds little to no assets, an attacker can donate underlying assets directly to it without minting shares, which inflates the share price the vault reports.

The exploit on the wstUSR market followed that path. The cvcrvUSD vault used as the oracle’s input held essentially no shares. The attacker donated about 2,000 crvUSD straight into it, then deposited 2 crvUSD to mint 1 wei of shares. After those two steps, convertToAssets(1e18) returned roughly 2e36 instead of a sensible number. The protocol’s exchange rate is computed as 1e36 / convertToAssets(1e18), and under Solidity integer arithmetic that rounded down to zero.

The dangerous boundary: from zero to borrow

The solvency check uses the exchange rate as a multiplier when computing the borrower’s LTV. With a zero rate, the LTV evaluates to zero, and zero is less than any positive max LTV. The check passes. 

That is how the attacker borrowed the full ceiling (~$10M) of the wstUSR pool against 1 wei of collateral. The solvency check exists to prevent borrows above the LTV ceiling. On this code path it did the opposite.

What kind of review catches this 

When I review an oracle exchange rate calculation in a lending protocol, the question I work through first is what the result looks like at the input boundaries. Not under normal market conditions. At the limits of what an attacker can push the input to.

For the ResupplyFi calculation, that question has two halves. What does 1e36 / oracle.getPrices(collateral) look like when the oracle returns a number close to zero? What does it look like when the oracle returns a very large number? Treat any arithmetic operation that feeds a solvency check as a boundary problem. The code is reasonable for the inputs the developer anticipated. The auditor’s job is the inputs the developer did not.

How a modern auditor automates this

When we audit a rate-and-solvency path at Veridise, the review doesn’t stop at the manual read. We encode what the reviewer noticed as a check that survives the engagement. 

For ResupplyFi, that means two artifacts. A custom static detector for the “division before multiplication through storage” shape, so any future change to the rate path is flagged at commit time. And a formal expression of the loan-to-value invariant we can hand to a fuzzer to exercise against the deployed market before user funds arrive. Next week’s Pre-Mortem walks through exactly that workflow, end to end. 

The tooling doesn’t replace the reviewer. It catches the arithmetic edge cases human review is most likely to miss, which frees our review time for the protocol-specific logic the tooling cannot reason about. 

What separates a modern auditor

Every new lending market a protocol ships is a new attack surface, even when the pair contract has been audited multiple times in prior incarnations. ResupplyFi’s pair logic has a long audit history. That history did not protect a freshly opened market with a fresh, manipulable oracle input. 

When we audit a system like this, we do two things a manual-only review does not. We treat the exchange rate calculation as a single point of failure and encode that thinking as a re-runnable check. We express the LTV invariant formally, separate from the implementation, so it can be exercised against the deployed market at any future commit.

The difference is durability. A traditional audit catches what one reviewer noticed on one read. A modern audit leaves a check behind. 

If your protocol is shipping new lending markets and you want this kind of audit before launch, request an audit or view our past DeFi audits to see how we approach oracle and collateral ratio verification. 

More by Veridise

Subscribe to our blog

Be the first to get the latest from Veridise — including educational articles on ZK and smart contracts, audit case studies, and updates on our tool development. Delivered twice a month.

smart contract audit cloud

Contact us for a security audit quote

Secure an earlier audit slot by reaching out early.