Thunder Loan

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

[M-01] Fee Calculation Precision Loss for Low-Decimal Tokens (e.g., USDC) Causes Revert

Description

In ThunderLoan.sol:246-251, getCalculatedFee() assumes 18 decimals for all tokens:

// File: src/protocol/ThunderLoan.sol                                                   
    function getCalculatedFee(IERC20 token, uint256 amount) public view returns (uint256

fee) {
//slither-disable-next-line divide-before-multiply
@> uint256 valueOfBorrowedToken = (amount * getPriceInWeth(address(token))) /
s_feePrecision;
//slither-disable-next-line divide-before-multiply
@> fee = (valueOfBorrowedToken * s_flashLoanFee) / s_feePrecision;
}

The contest specification explicitly includes USDC (6 decimals). If a user borrows 100
USDC (amount = 100e6), assuming 1 ETH = $2,000 (getPriceInWeth = 5e14):

                       100 × 10⁶ × 5 × 10¹⁴                                             
valueOfBorrowedToken = ──────────────────── = 50, 000                                   
                               10¹⁸                                                     
                                                                                        
      50, 000 × 3 × 10¹⁵                                                                
fee = ────────────────── = 0                                                            
             10¹⁸                                                                       

When fee == 0, AssetToken.updateExchangeRate(0) is executed:

uint256 newExchangeRate = s_exchangeRate * (totalSupply() + fee) / totalSupply();       
if (newExchangeRate <= s_exchangeRate) {                                                
    revert AssetToken__ExhangeRateCanOnlyIncrease(s_exchangeRate, newExchangeRate);     
}                                                                                       

Because newExchangeRate == s_exchangeRate, updateExchangeRate reverts, causing all flash
loans for low-decimal tokens like USDC to fail.

Risk

Likelihood: High

Impact: Medium

Proof of Concept

For any token with ≤ 6 decimals (such as USDC or USDT):

  1. User calls thunderLoan.flashloan(...) for USDC.

  2. getCalculatedFee() divides by 10¹⁸ twice against a 6-decimal amount, truncating fee to

  3. assetToken.updateExchangeRate(0) evaluates newExchangeRate <= s_exchangeRate and
    reverts with AssetToken__ExhangeRateCanOnlyIncrease.

  4. Flash loans cannot be taken for USDC.

Recommended Mitigation

Normalize token decimals when calculating fees, or compute fees as a basis-point
proportion directly in the borrowed token's native units without double division by
s_feePrecision:

--- a/src/protocol/ThunderLoan.sol                                                      
+++ b/src/protocol/ThunderLoan.sol                                                      
@@ -246,6 +246,6 @@ contract ThunderLoan is Initializable, OwnableUpgradeable,          

UUPSUpgradeable, Ora
function getCalculatedFee(IERC20 token, uint256 amount) public view returns
(uint256 fee) {
- uint256 valueOfBorrowedToken = (amount * getPriceInWeth(address(token))) /
s_feePrecision;
- fee = (valueOfBorrowedToken * s_flashLoanFee) / s_feePrecision;
+ fee = (amount * s_flashLoanFee) / s_feePrecision;
}

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 2 hours 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!