Thunder Loan

AI First Flight #7
Beginner FriendlyFoundryDeFiOracle
EXP
View results
Submission Details
Impact: low
Likelihood: low
Invalid

Unnecessary `repay` Function Creates Confusion and Gas Inefficiency

[L-1] Unnecessary repay Function Creates Confusion and Gas Inefficiency

Description

The ThunderLoan contract includes a repay function that allows flash loan borrowers to repay their loans. However, this function is unnecessary because the flashloan function already checks the balance after the callback to ensure repayment.

Borrowers can simply transfer tokens back to the AssetToken contract without calling repay. The repay function adds no value and creates confusion about the correct way to repay flash loans.

// This function is never required
function repay(IERC20 token, uint256 amount) public {
if (!s_currentlyFlashLoaning[token]) {
revert ThunderLoan__NotCurrentlyFlashLoaning();
}
AssetToken assetToken = s_tokenToAssetToken[IERC20(token)];
token.safeTransferFrom(msg.sender, address(assetToken), amount);
}

The flashloan function checks the balance regardless of how tokens are repaid:

uint256 endingBalance = token.balanceOf(address(assetToken));
if (endingBalance < startingBalance + fee) {
revert ThunderLoan__NotPaidBack(startingBalance + fee, endingBalance);
}

Risk

Likelihood:

  • Affects all flash loan integrators who study the interface

  • Creates confusion about intended repayment method

  • Gas inefficiency occurs whenever repay is used instead of direct transfer

Impact:

  • Borrowers waste gas calling repay when direct transfer would suffice

  • Code complexity increases with unused functionality

  • Potential for bugs if future changes assume repay must be called

  • Confusing for auditors and integrators

Proof of Concept

Both repayment methods work identically:

function testRepayIsUnnecessary() public setAllowedToken hasDeposits {
// Method 1: Using repay function (wastes gas)
thunderLoan.flashloan(
address(mockFlashLoanReceiver), // Uses repay()
tokenA,
100e18,
""
);
// Method 2: Direct transfer (more efficient)
// Both methods result in the same outcome
// The flashloan function only checks the final balance
}

Recommended Mitigation

Remove the repay function entirely and update documentation to clarify that borrowers should simply ensure the AssetToken contract has sufficient balance by the end of the callback.

- function repay(IERC20 token, uint256 amount) public {
- if (!s_currentlyFlashLoaning[token]) {
- revert ThunderLoan__NotCurrentlyFlashLoaning();
- }
- AssetToken assetToken = s_tokenToAssetToken[IERC20(token)];
- token.safeTransferFrom(msg.sender, address(assetToken), amount);
- }

Update documentation to clarify:

/**
* @notice Executes a flash loan
* @dev Borrowers must ensure the AssetToken contract receives
* the borrowed amount plus fee by the end of executeOperation.
* Repayment can be done via direct transfer or SafeERC20.safeTransfer.
*/
function flashloan(...) external { ... }
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 11 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!