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

Tokens with a number of decimals not equal to 18 may generate LP tokens with non-ideal value, leading to error prone display

Summary

Given the fact that LP tokens of AssetToken ERC20 contract are all 18 decimals by default with the current implementation, allowing a token with another number of decimals would result in a non 1-1 ratio for the creation of LP tokens with STARTING_EXCHANGE_RATE.

Vulnerability Details

3 of the tokens that could become allowed in the protocol have different number of decimals than 18 :

  • USDT has 6 decimals

  • USDC has 6 decimals

  • ZIL has 12 decimals

In the case of USDC for example, depositing 1000 USDC is the same as passing 1000*1e6 for amount in the deposit function. mintAmount will be the same as amount before the first flashloan occurs, as:

uint256 mintAmount = (amount * assetToken.EXCHANGE_RATE_PRECISION()) / exchangeRate;

Finally, LP tokens will be minted with mintAmount = 1000*1e6:

assetToken.mint(msg.sender, mintAmount);

This means the liquidity provider will receive 1e9 of the LP tokens, which 0.000000001LP token. This could be really annoying and error prone. Ideally, the protocol should be able to mint a LP token with the same number of decimals.

Impact

The impact of this issue is MEDIUM as it generates error prone conversion rates with many power of ten between LP tokens and underlying tokens. It also induces many display issues. In the case of USDC and USDT, the difference between the balance of LP tokens and underlying tokens will be 1e12 factor. For ZIL, it will be 1e6.

Tools Used

Manual

Recommendations

I would suggest to allow modification of the number of decimals of a new AssetToken contract when it is deployed. That way, it could be easy to create a LP token with the same number of decimals as the underlying asset.

We could add another input parameter in AsssetToken constructor :

constructor(
address thunderLoan,
IERC20 underlying,
string memory assetName,
string memory assetSymbol,
uint8 numberOfDecimals
)

and assign i_numberOfDecimals = numberOfDecimals; after declaring a new immutable variable:

uint8 private immutable i_numberOfDecimals;

Then AssetToken should override decimals function of the ERC20 contract inherited :

function decimals() public view override returns (uint8) {
return i_numberOfDecimals;
}

Ultimately, ThunderLoan and ThunderLoanUpgraded contracts should modify the deployment of new AssetToken contracts to include the number of decimals:

AssetToken assetToken = new AssetToken(address(this), token, name, symbol, ERC20(address(token)).decimals());

I used the ERC20 wrapper after importing it because the IERC20 interface from Open Zeppelin doesn't classically include the decimals() function.

Updates

Lead Judging Commences

0xnevi Lead Judge
almost 2 years ago
0xnevi Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Other
tadev Submitter
almost 2 years ago
0xnevi Lead Judge
almost 2 years ago
tadev Submitter
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.