Flash Loan Exploit Generator
Sigvex exploit generator that validates flash loan vulnerabilities by comparing contract execution under normal vs. temporarily-inflated balance conditions.
Flash Loan Exploit Generator
Overview
The flash loan exploit generator validates findings from the flash_loan detector by executing the target contract’s bytecode under two world-state configurations: one with a realistic attacker balance and one with an artificially inflated balance (simulating a flash loan). If the contract’s behavior changes between the two scenarios — particularly if a transaction that normally fails suddenly succeeds — the contract is vulnerable to flash loan manipulation.
Flash loan attacks have caused some of the largest DeFi losses on record. Common patterns include single-block price manipulation via DEX swaps, collateral inflation in lending protocols, and governance vote manipulation.
Note: Exploit generation in Sigvex is for vulnerability validation purposes only.
Attack Scenario
- Setup: The attacker takes a flash loan of
1,000,000,000tokens. The simulation sets the attacker’s balance to this large amount, creating a temporary window where the attacker appears to hold enormous liquidity within a single transaction. - Trigger: The attacker calls the vulnerable function (typically a
swap,trade, orliquidateentry point). The calldata is prefixed with selector0x0224_08e8(swap(uint256,uint256,address,bytes)) if no finding location is available. - Exploitation: The protocol reads balances or reserves to calculate prices, collateral ratios, or swap outputs. With a flash-loan-inflated balance, these calculations return values far outside normal operating ranges, allowing the attacker to extract value (e.g., borrow against inflated collateral, execute arbitrage at artificial prices, or trigger a cascade of liquidations).
- Impact: The attacker repays the flash loan within the same transaction and keeps the extracted profit. The victim protocol’s reserves or user balances are permanently damaged.
Exploit Mechanics
The generator executes two scenarios and compares their outcomes:
Scenario 1 — Normal balance (attacker_balance = 100_000):
- Represents an attacker with ordinary funds
- Used as a baseline for expected contract behavior
Scenario 2 — Flash loan balance (attacker_balance = 1_000_000_000):
- Simulates a flash loan of 1 billion tokens/wei
- Pool reserves are also manipulated in the simulated world state to reflect the reserve imbalance after a large buy using the flash-loaned funds
Verdict logic:
| Scenario 1 result | Scenario 2 result | Finding |
|---|---|---|
| Reverted | Succeeded | Critical (confidence 0.90): flash loan makes otherwise-impossible transaction succeed |
| Succeeded | Succeeded, gas delta > 100k | Likely (confidence 0.65): different execution paths indicate flash loan sensitivity |
| Succeeded | Succeeded, gas delta ≤ 100k | Not vulnerable |
| Succeeded | Reverted | Not vulnerable (protection in place) |
The generated PoC uses the Aave V3 flash loan interface:
import "@aave/core-v3/contracts/flashloan/base/FlashLoanSimpleReceiverBase.sol";
contract FlashLoanAttacker is FlashLoanSimpleReceiverBase {
function executeOperation(
address asset,
uint256 amount,
uint256 premium,
address initiator,
bytes calldata params
) external override returns (bool) {
// Exploit vulnerable contract here with inflated balance
// ...
uint256 amountOwed = amount + premium;
IERC20(asset).approve(address(POOL), amountOwed);
return true;
}
}
Remediation
- Detector: Flash Loan Detector
- Remediation Guide: Flash Loan Remediation
Use time-weighted average price (TWAP) oracles instead of spot prices. Chainlink Price Feeds provide manipulation-resistant off-chain data. For DEX-derived prices, Uniswap V3’s TWAP oracle requires sustained price pressure across multiple blocks to manipulate, making single-block flash loan attacks ineffective:
// VULNERABLE: Reads instantaneous spot price
function getPrice() external view returns (uint256) {
(uint112 reserve0, uint112 reserve1,) = pair.getReserves();
return reserve1 * 1e18 / reserve0; // flash-loan manipulable
}
// SECURE: Uses TWAP from Uniswap V3
function getPrice() external view returns (uint256) {
return oracle.consult(token, twapPeriod); // 30-minute TWAP
}