Flash loan fee calculations are expected to output a fee denominated in the borrowed asset (token) so that endingBalance >= startingBalance + fee verifies payment in that exact token.
OracleUpgradeable::getPriceInWeth() returns the asset price denominated in WETH. When getCalculatedFee() computes (amount * priceInWeth) / 1e18, the fee is calculated in WETH units, but then enforced as if it were denominated in token. Furthermore, for WETH loans, tswapPoolFactory.getPool(weth) returns address(0), causing any WETH flash loan to permanently revert.
Likelihood:
Occurs on every fee calculation for non-WETH tokens with prices differing from 1:1 WETH valuation.
Occurs 100% of the time whenever any user attempts to borrow WETH via flash loan.
Impact:
Severe fee undercharge for low-priced tokens and prohibitive overcharge for high-priced tokens.
Complete Denial of Service (DoS) preventing flash loans of WETH, the most critical asset in DeFi.
The exploit operates through the following steps:
User requests a flash loan of tokenA where 1 tokenA = 0.001 WETH (1,000 tokenA per WETH).
The contract calculates the fee in WETH units, but demands payment in tokenA, undercharging the fee by 1,000x.
User attempts to borrow WETH; the call reverts with Oracle__PoolDoesNotExist because no WETH-WETH pool exists on TSwap.
Compute flash loan fees strictly as a percentage of the borrowed token amount, eliminating the need for oracle conversion in fee calculation, and add a special case for WETH in OracleUpgradeable.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.