Incorrect ticket calculation for Tokens with fee-on-transfer
purchaseTickets calculates tickets from the input _amount but transfers the tokens via safeTransferFrom, so fee-on-transfer tokens credit users with more tickets than the contract actually receives.
Description
The purchaseTickets function in the MonadexV1Raffle contract does not account for tokens that implement a fee-on-transfer mechanism. These tokens deduct a fee from the transfer amount, resulting in the recipient receiving less than the amount specified in the transfer.
The current implementation calculates the number of tickets to mint based on the input _amount. However, it then transfers the tokens using:
IERC20(_token).safeTransferFrom(_swapper, address(this), _amount);
For fee-on-transfer tokens, the actual amount received by the contract will be less than _amount. This discrepancy leads to an incorrect calculation of tickets, where users receive more tickets than they should based on the actual amount of tokens received by the contract.
Impact
- Users of fee-on-transfer tokens would receive more raffle tickets than they should, giving them an unfair advantage over users of standard tokens.
- The raffle system would consistently overvalue fee-on-transfer tokens, potentially leading to economic exploits or imbalances in the protocol.
- The contract's internal accounting of received tokens versus issued tickets would be inaccurate, potentially causing issues in other parts of the system.
Recommendation
To address this issue, implement a two-step process for purchasing tickets with fee-on-transfer tokens:
First, transfer the tokens and calculate the actual amount received:
uint256 balanceBefore = IERC20(_token).balanceOf(address(this));IERC20(_token).safeTransferFrom(_swapper, address(this), _amount);uint256 balanceAfter = IERC20(_token).balanceOf(address(this));uint256 actualAmount = balanceAfter - balanceBefore;
Then, use the actualAmount to calculate the number of tickets to mint:
uint256 ticketsToMint = previewPurchase(_token, actualAmount, _multiplier);

