Beginner FriendlyFoundryDeFiOracle
100 EXP
View results
Submission Details
Severity: high
Invalid

Not all tokens have 18 decimals

Summary

In contract ThunderLoan.sol is written: // The fee in WEI, it should have 18 decimals. Each flash loan takes a flat fee of the token price. But the protocol works also with tokens that have fewer than 18 decimals such as USDT (6 Decimals), USDC (6 Decimals) and ZIL (12 Decimals).

Vulnerability Details

The function ThunderLoan::getCalculatedFee calculates the fee for a flash loan based on the value of the borrowed token in WETH (wrapped Ether). It assumes that the token has 18 decimals, which is a standard for many ERC20 tokens.

But USDC and USDT are examples of tokens that use 6 decimals, and ZIL uses 12 decimals. If these tokens are used with the getCalculatedFee() function without adjusting for their decimal places, the function could return incorrect results.

Specifically, the function would likely overestimate the fee for these tokens. This is because the function would interpret 1 USDC, USDT, or ZIL as being worth 10^12 (for USDC and USDT) or 10^6 (for ZIL) times more than it actually is. This could result in the contract charging a much higher fee than intended.

Also, this issue is presented in function ThunderLoanUpgraded::getCalculatedFee.

Impact

Let's take an example where the token is USDC which has 6 decimals and the amount of the flash loan is 100 USDC (which is represented as 100 * 10^6 = 100,000,000 in the smart contract due to the 6 decimals).

Let's also assume that the price of USDC in WETH is 0.0004 WETH (since USDC is a stablecoin, its price in terms of ETH will depend on the current price of ETH in USD).

The ThunderLoan::getCalculatedFee function calculates the fee as follows:

uint256 valueOfBorrowedToken = (amount * getPriceInWeth(address(token))) / s_feePrecision;
uint256 fee = (valueOfBorrowedToken * s_flashLoanFee) / s_feePrecision;

Substituting the values:

valueOfBorrowedToken = (100,000,000 * 0.0004) / 1e18;
fee = (valueOfBorrowedToken * 3e15) / 1e18;

However, because the function assumes the token has 18 decimals, it will interpret the amount as 100,000,000 * 10^12 (due to the extra 12 decimal places it assumes exist). This will result in the valueOfBorrowedToken and fee being calculated as much larger values than they should be.

Tools Used

Manual Review, VS Code

Recommendations

To handle tokens with different decimal places, the contract should ideally take into account the number of decimals of the token when calculating the fee. This could be done by querying the decimals function of the ERC20 token contract and adjusting the calculation accordingly.

Updates

Lead Judging Commences

0xnevi Lead Judge
about 2 years ago
0xnevi Lead Judge about 2 years ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

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