Some tokens (e.g., USDC) contain a special case for amount == type(uint256).max in their transfer functions that results in only the user's balance being transferred. This may cause issues with systems that transfer a user-supplied amount to their contract and then credit the user with the same value in storage (e.g., Vault-type systems) without checking the amount that has actually been transferred.
The special case for amount == type(uint256).max in the transfer function of some tokens, like USDC, can indeed cause issues with systems that transfer a user-supplied amount to their contract and then credit the user with the same value in storage without checking the amount that has actually been transferred. This is because when amount == type(uint256).max, the token's transfer function will transfer the maximum possible amount of tokens, which could be more or less than the user-supplied amount.
The ThunderLoan::flashLoan function calls the getCalculatedFee() function and then transfers the calculated fee to the assetToken contract. If the token contract has a special case for amount == type(uint256).max, it could transfer more or less tokens than the calculated fee, which would lead to incorrect balances in the assetToken contract and in the user's account. This is also valid for the ThunderLoanUpgraded::flashLoan function.
Manual Review, VS Code
To prevent this issue, you should modify the flashLoan() function in contracts ThunderLoan.sol and ThunderLoanUpgraded.sol to check the amount of tokens that has actually been transferred after calling the getCalculatedFee() function. You can do this by calling the balanceOf function of the token contract after the transfer, and then comparing this amount with the calculated fee.
In this modified flashLoan() function, initialBalance is the balance of the assetToken contract before the transfer, and finalBalance is the balance after the transfer. The require statement checks that the difference between finalBalance and initialBalance is equal to the calculated fee, which ensures that the correct amount of tokens has been transferred.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.