Reproduced Exploit
Vault4626 — Donation of Non-Asset WETH Inflates totalAssets() and Is Paid Out on redeem()
1. totalAssets() (Vault4626.sol:496-536) returns idle USDC + LP value plus TWAP-quoted vault balances of the non-asset token (WETH):
Loss
~13.53 WETH profit (18366634484619156667 − 4837426434749649311 = 13529208039869487356 wei)
Chain
Base
Category
defi
Date
Jun 2026
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. Step by Solidity line or by opcode across all call depths; the source line, Stack, Memory, Storage, Transient storage and Return value stay in sync. Click any opcode or source line to jump. No backend, no live RPC.
Source & credit. Exploit reproduction, trace data, and analysis adapted from DeFiHackLabs by SunWeb3Sec — an open registry of reproduced on-chain exploits. Standalone Foundry PoC and full write-up: 2026-06-Vault4626_exp in the
evm-hack-registrymirror. Upstream DeFiHackLabs PoC:src/test/…/Vault4626_exp.sol.
Vulnerability classes: vuln/defi/donation-attack · vuln/logic/incorrect-accounting · vuln/defi/flash-loan-attack
Reproduction: offline Foundry project at this folder. Trace: output.txt. Verified source: src_Vault4626.sol (implementation) behind proxy
0x72dbAA8A….
Key info#
| Loss | ~13.53 WETH profit (18366634484619156667 − 4837426434749649311 = 13529208039869487356 wei) |
| Vulnerable contract | Vault4626 impl — 0xD08579102fc28355C5839019b730Ce58F84E6a4d |
| Vault proxy | 0x72dbAA8A09d71D09c6De0de439968e1E7c122020 |
| Asset / non-asset | USDC (0x8335…2913) / WETH (0x4200…0006) |
| Attacker | 0xA27eAE743Cd8C03E9b7c25ebF43DADbBC6Df9bFA |
| Attack tx | 0x2f2e12fbdf541c28f3667153e5338f73a313096338dc5ca592453566debcd790 |
| Chain / block | Base / 47,958,574 / June 2026 |
| Bug class | totalAssets() quotes donated idle non-asset WETH into USDC value, while redeem() also transfers that WETH to the redeemer — double-counting donation as both share price and physical payout |
TL;DR#
-
totalAssets()(Vault4626.sol:496-536) returns idle USDC + LP value plus TWAP-quoted vault balances of the non-asset token (WETH):vaultNonAssetQuoted = getQuoteAtTick(tick, vaultNonAsset, nonAssetToken, asset); return idle + assetInLP + quoted + vaultNonAssetQuoted; -
redeem()(Vault4626.sol:390-490) sizes the USDC payout fromconvertToAssets(shares)(which uses inflatedtotalAssets()), then additionally transfers a pro-rata share of the vault's WETH to the redeemer. -
Attack: Morpho-flash USDC → deposit for almost all shares → Balancer-flash WETH and donate it to the vault → redeem inflated shares → receive both overpriced USDC and the donated WETH → swap surplus USDC to WETH → repay flash loans → keep ~13.53 WETH.
-
Reproduced: attacker WETH
4.837 → 18.367(output.txt); vaulttotalAssetsdrops sharply.
Vulnerable code#
// totalAssets — quotes donated WETH into share price
uint256 vaultNonAsset = IERC20(nonAssetToken).balanceOf(address(this));
uint256 vaultNonAssetQuoted = vaultNonAsset > 0
? VaultMathLib.getQuoteAtTick(tick, vaultNonAsset, nonAssetToken, address(asset)) : 0;
return idle + assetInLP + quoted + vaultNonAssetQuoted;
// redeem — pays USDC from convertToAssets (uses totalAssets) AND transfers WETH
assets = convertToAssets(shares); // inflated by donation
...
_safeTransfer(nonAssetToken, receiver, nonAssetToSend); // also pays the WETH
Attack flow#
Recommendation#
- Do not count unsolicited non-asset balances in
totalAssets()unless they are already reserved for a specific LP/fee accounting bucket that is not also transferred on redeem. - Prefer: only count strategy-reported balances; ignore raw
balanceOf(vault)for non-asset tokens that redeem will pay out. - Donation-attack hardening: track accounting balances (not raw ERC20 balances) for share price.
References#
- Attack tx: https://basescan.org/tx/0x2f2e12fbdf541c28f3667153e5338f73a313096338dc5ca592453566debcd790
- Analysis: https://x.com/DefimonAlerts/status/2071495744071086510
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 2026-06-Vault4626_exp (evm-hack-registry mirror).
- Upstream DeFiHackLabs PoC:
Vault4626_exp.sol. - Attack transaction: view on explorer.
Alerts & third-party analyses
- Original alert / thread: post on X.
- DeFiHackLabs incident explorer: search "Vault4626".
- Web3Sec X hacked database: search.
- Rekt leaderboard: search.
- Solodit incident search: search.
These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.