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

`ThunderLoan::deposit` Doesn't Work Well With ERC20 Tokens With A Fee On Transfer

Summary

Accepted tokens like USDT, STA, PAXG charge a fee on transfer, that isn't accounted during the minting of AssetToken when a user provides liquidity to the protocol.

Vulnerability Details

Let's assume a user provides 10,000 USDT as liquidity, according to the logic in deposit that same amount is used to mint AssetToken:

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

But since a fee is charged the actual quantity deposited in AssetToken will be less than amount. So the liquidity provider will receive an amount of AssetToken greater than the actual deposit.

Impact

Liquidity providers can receive more AssetToken than the their actual deposits, giving them a bigger ownership of the pool that they actually own.

Tools Used

Manual.

Recommendations

Read the balance of token in AssetToken before and after the deposit to calculate a delta that represents the actual amount deposited by the user to know how many tokens to mint and use the delta to calculate the fee.

diff --git a/src/protocol/ThunderLoan.sol.orig b/src/protocol/ThunderLoan.sol
index 1031975..efeb6cc 100644
--- a/src/protocol/ThunderLoan.sol.orig
+++ b/src/protocol/ThunderLoan.sol
@@ -163,12 +163,17 @@ contract ThunderLoan is Initializable, OwnableUpgradeable, UUPSUpgradeable, OracleUpgradeable
function deposit(IERC20 token, uint256 amount) external revertIfZero(amount) revertIfNotAllowedToken(token) {
AssetToken assetToken = s_tokenToAssetToken[token];
uint256 exchangeRate = assetToken.getExchangeRate();
- uint256 mintAmount = (amount * assetToken.EXCHANGE_RATE_PRECISION()) / exchangeRate;
- emit Deposit(msg.sender, token, amount);
+
+ uint256 balanceBefore = token.balanceOf(address(assetToken));
+ token.safeTransferFrom(msg.sender, address(assetToken), amount);
+ uint256 balanceAfter = token.balanceOf(address(assetToken));
+ uint256 amountDeposited = balanceAfter - balanceBefore;
+
+ uint256 mintAmount = (amountDeposited * assetToken.EXCHANGE_RATE_PRECISION()) / exchangeRate;
+ emit Deposit(msg.sender, token, amountDeposited);
assetToken.mint(msg.sender, mintAmount);
- uint256 calculatedFee = getCalculatedFee(token, amount);
+ uint256 calculatedFee = getCalculatedFee(token, amountDeposited);
assetToken.updateExchangeRate(calculatedFee);
- token.safeTransferFrom(msg.sender, address(assetToken), amount);
}
Updates

Lead Judging Commences

0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

fee on transfer

Support

FAQs

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