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

Decimal Incompatibility Issues with Non-18 Decimal Tokens

Vulnerability Details

The ThunderLoan protocol has hard-coded the precision for fee calculations and exchange rate as 1e18, which assumes that all tokens have 18 decimals. This is a common standard for many ERC20 tokens, but not all tokens follow this standard (USDC and ZIL for example). Tokens with a different decimal count will result in incorrect fee calculations and exchange rates when interacting with the ThunderLoan protocol.

The fee and exchange rate calculations are exemplified in the following snippets:

File: ThunderLoan.sol
s_feePrecision = 1e18;
s_flashLoanFee = 3e15; // 0.3% ETH fee
File: ThunderLoan.sol
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;
}
File: AssetToken.sol
uint256 public constant EXCHANGE_RATE_PRECISION = 1e18;
uint256 private constant STARTING_EXCHANGE_RATE = 1e18;
File: AssetToken.sol
function updateExchangeRate(uint256 fee) external onlyThunderLoan {
// ...existing code...
uint256 newExchangeRate = s_exchangeRate * (totalSupply() + fee) / totalSupply();
// ...existing code...
}

Impact

The hardcoded precision can lead to significant discrepancies in value calculations for tokens with non-standard decimals. If a token has fewer than 18 decimals, the protocol may calculate fees and exchange rates that are disproportionately high, unfairly penalizing users of such tokens. Conversely, if a token has more than 18 decimals, the protocol might undercharge for its services, leading to a loss of potential revenue and unfair benefit to users of these tokens.

Recommendations

To resolve this issue, the protocol should dynamically adjust the precision based on the decimal count of the token in question. This can be achieved by querying the decimals() function that many ERC20 tokens implement. Below is an example of how the getCalculatedFee function could be adjusted to accommodate tokens with different decimals:

File: ThunderLoan.sol
function getCalculatedFee(IERC20 token, uint256 amount) public view returns (uint256 fee) {
uint256 tokenDecimals = token.decimals();
uint256 feePrecision = 10**tokenDecimals;
uint256 valueOfBorrowedToken = (amount * getPriceInWeth(address(token))) / feePrecision;
fee = (valueOfBorrowedToken * s_flashLoanFee) / feePrecision;
}

For the AssetToken exchange rate updates, a similar dynamic adjustment should be made to ensure the exchange rate remains fair and accurate regardless of the token's decimals:

File: AssetToken.sol
function updateExchangeRate(uint256 fee) external onlyThunderLoan {
uint256 tokenDecimals = IERC20(address(this)).decimals();
uint256 exchangeRatePrecision = 10**tokenDecimals;
// ...existing code...
uint256 newExchangeRate = s_exchangeRate * (totalSupply() + fee) / totalSupply();
// ...existing code...
}

By making these changes, the ThunderLoan protocol can ensure fair treatment of all tokens regardless of their decimal precision, maintain the protocol's economic balance, and prevent any potential exploits or user dissatisfaction arising from the decimal incompatibility.

Updates

Lead Judging Commences

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

Support

FAQs

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