Root Cause
The FlashLoopAdapter's open() and close() functions implemented caller authentication by calling back to msg.sender:
// Reconstructed vulnerable authentication pattern
function open(/* params */) external {
// BUG: authentication is performed by asking the CALLER
require(
IGnosisSafe(msg.sender).isModuleEnabled(address(this)),
"Module not enabled"
);
// ... proceed with Aave debt management
_swap(/* caller-supplied router, calldata */);
}
Because the check relies solely on msg.sender.isModuleEnabled(address(this)), any contract that implements isModuleEnabled() returning true passes the authentication. The adapter had no whitelist of known Safe deployments and no on-chain registry check. Additionally, the _swap() helper accepted a caller-specified router address and arbitrary calldata, amplifying the blast radius.
Aave v3 itself was not affected; the vulnerability was entirely within the third-party adapter logic.
Attack Steps
| Step | Action |
|---|---|
| 1 | Attacker deploys a malicious contract with isModuleEnabled() hard-coded to return true |
| 2 | Calls open() or close() on FlashLoopAdapter from the malicious contract |
| 3 | Authentication check passes — adapter proceeds as if caller is a legitimate Gnosis Safe |
| 4 | Attacker uses a Morpho flash loan to source ~1,335 WETH |
| 5 | Flash loan proceeds repay the Aave v3 debt position of the targeted Safe wallets |
| 6 | With debt cleared, the adapter's collateral-withdrawal path executes, extracting ~1,306 weETH |
| 7 | Flash loan repaid; attacker nets |
Impact
- Loss: ~$305,000 (approximately 114 ETH net profit)
- Victims: Two Aave-linked Gnosis Safe wallets on Ethereum mainnet
- Aave v3: Confirmed unaffected by Aave founder Stani Kulechov; core Aave pools were not accessed
- Detection: SlowMist and Defimon Alerts both flagged the anomalous flash-loan flow shortly after execution
Lessons for Auditors
- Never authenticate by interrogating the caller. Any authentication check that calls back to
msg.senderto ask "are you authorized?" is trivially defeated by a malicious implementation. Authentication must be performed against an immutable registry or a pre-approved allowlist stored in the contract itself. - Restrict external swap routers. Allowing callers to specify arbitrary router addresses and calldata turns any DeFi integration into a potential drain vector. Use a hardcoded or governance-gated whitelist of approved routers.
- Audit integration-layer contracts with the same rigour as core protocols. Third-party adapters that interact with high-value positions (Aave collateral, Gnosis Safe wallets) are first-class attack surfaces regardless of whether the underlying protocol is audited.
- Flash loans do not add risk — but they remove capital barriers. This exploit required no upfront capital; any attacker with gas can repeat it. Protections must not assume the attacker lacks funds.