ResupplyFi Hack Analysis
ResupplyFi Hack Analysis

Overview:
On June 26, 2025, ResupplyFi (@ResupplyFi) — a decentralized lending protocol — was exploited for approximately $9.56 million. The attacker targeted the ResupplyPair contract which uses the manipulated rate, just hours after its deployment. The root cause was an exchange rate manipulation bug triggered via a classic ERC4626 “first donation” vault attack, resulting in a division-by-large-value scenario that collapsed the exchangeRate to zero.
This manipulated rate was used to compute the borrower’s Loan-to-Value (LTV) in the _isSolvent() check. Since ltv = 0 when exchangeRate = 0, the attacker bypassed the solvency check and borrowed $10 million reUSD using just 1 wei of collateral. This vulnerability falls under OWASP SC03: Logic Errors.
Smart Contract Hack Overview:
- Victim Contract: 0x6e90c
- Attack Transaction: 0xffbbd
- Attacker Addresses: 0x6D9f6, 0x31129
- OWASP SC Top 10: SC03: Logic Errors.

Decoding the Smart Contract Vulnerability:
- The root cause of the vulnerability that enabled the ResupplyFi exploit stemmed from a flawed implementation of the
_updateExchangeRate()and_isSolvent()functions within theResupplyPairCore.solcontract. Specifically, the contract relied on an inverse exchange rate calculation using a price oracle tied to an ERC4626 vault (cvcrvUSD), whose share price (pricePerShare) was used directly to derive the value of collateral.

- In
_updateExchangeRate(), the contract retrieves the price using an oracle call togetPrices(address(collateral)), which returns thepricePerShareof the underlying ERC4626 vault. It then inverts this price using1e36 / price, because debt is denominated in units of collateral.
price = IOracle(_exchangeRateInfo.oracle).getPrices(address(collateral));
_exchangeRate = 1e36 / IOracle(_exchangeRateInfo.oracle).getPrices(address(collateral));
- Because the vault was nearly empty, the attacker exploited the ERC4626 donation logic — they made a small deposit and a large donation to the vault, drastically inflating
pricePerShare. As a result, the oracle returned an extremely high price. - This led to
1e36 / pricebeing evaluated to0due to Solidity’s integer division flooring behavior. Critically, the implementation did not include any validation likerequire(_exchangeRate > 0), so this invalid value was saved to storage as the current exchange rate.

- This incorrect
_exchangeRate = 0value then flowed into the_isSolvent()function, which uses the exchange rate to calculate a borrower’s Loan-to-Value (LTV) ratio. - The
_isSolvent()function is responsible for ensuring that users cannot borrow more than they are allowed to, based on the current value of their collateral. It blindly uses the stored_exchangeRateto compute the user’s effective LTV ratio. However, if_exchangeRateis zero (as manipulated by the attacker), then the entire numerator of the LTV formula collapses to zero, and_ltv = 0.
_ltv = ((_borrowAmount * _exchangeRate * LTV_PRECISION) / EXCHANGE_PRECISION) / _collateralAmount;
- This causes the function to always return
true, regardless of how much the user is attempting to borrow, as long as they have a non-zero amount of collateral (even 1 wei). This behavior completely bypasses the core economic invariant that the borrowed amount must be backed by sufficient collateral. - As a result, the attacker was able to borrow $10 million worth of reUSD using just 1 wei of collateral. After swapping and redistributing the stolen funds, they successfully escaped with an estimated profit of $9.56 million, split across 2 addresses.
Attack Sequence:
Attacker deposited 1 wei into an empty
cvcrvUSDERC4626 vault, then made a large donation to artificially inflatepricePerShare.
Called
borrow()on the newly deployed ResupplyPair, triggering an oracle price fetch andexchangeRate = 1e36 / price.
Due to the inflated price,
exchangeRatecomputed to zero via Solidity floor division.
The
_isSolvent()check returnedtrue, since LTV became zero, bypassing collateral validation.
Attacker borrowed 10 million reUSD using just 1 wei of collateral, and walked away with ~$9.56 million split across multiple wallets.

- Within few hours of the exploit, ResupplyFi governance executed a series of emergency transactions (e.g.,
execTransaction) to zero out borrow limits and reset interest rates, as seen inUpdateRateandSetBorrowLimitevents.

- These actions were intended to freeze the protocol’s borrowing capability and limit further losses while further investigations are on-going. Read more here: https://x.com/ResupplyFi/status/1938092252431036491

Mitigation and Best Practices:
- Always add sanity checks like
require(_exchangeRate > 0)and upper/lower bounds to prevent zero or extreme values from being written to storage due to manipulated oracle inputs or division errors. - Also, avoid using uninitialized or low-liquidity ERC4626 vaults as collateral or oracles. Consider enforcing a minimum liquidity threshold before a vault can be used for borrowing or price calculations.
- Ensure a minimum borrow threshold relative to the value of collateral. And temporarily cap borrowing limits on newly deployed pairs until they are battle-tested.
- To prevent such vulnerabilities, the best Smart Contract auditors must examine the Smart Contracts for logical issues. We at CredShields provide smart contract security and end-to-end security of web applications and externally exposed networks. Our public audit reports can be found on https://github.com/Credshields/audit-reports. Schedule a call at https://credshields.com/
- Scan your Solidity contracts against the latest common security vulnerabilities with 494+ detections at SolidityScan.

Conclusion:
SolidityScan is an advanced smart contract scanning tool that discovers vulnerabilities and reduces risks in code. Request a security audit with us, and we will help you secure your smart contracts. Signup for a free trial at https://solidityscan.com/signup
Follow us on our Social Media for Web3 security-related updates.