Summary
When a user bids DaiGoldAuction the auction uses a fee-on-transfer token, incorrect accounting is made and the user is accounted for with more tokens than he deposited. A check for the auctions's balance before and after is not done and the amount that comes from the input is directly added to the depositor's balance as well as to totalBidTokenAmount
function bid(uint256 amount) external virtual override onlyWhenLive {
if (amount == 0) revert CommonEventsAndErrors.ExpectedNonZero();
> bidToken.safeTransferFrom(msg.sender, treasury, amount);
uint256 epochIdCache = _currentEpochId;
depositors[msg.sender][epochIdCache] += amount;
EpochInfo storage info = epochs[epochIdCache];
info.totalBidTokenAmount += amount;
emit Deposit(msg.sender, epochIdCache, amount);
}
Vulnerability Details
Imagine the auction starts with a fee-on-transfer token and Alice bids 100 tokens.
The auction contract will receive 98 because of the fee, but it will account for 100 tokens.
At the end of the auction, Alice will receive more gold than she deserves
Impact
This leads to incorrect accounting and users will claim more TempleGold than they should
Tools Used
Manual review
Recommendations
If you want to allow fee-on-transfer tokens use the bellow update
Check the balance of the contract before and after the transfer of the tokens as done in the SpiceAuction.sol
function bid(uint256 amount) external virtual override onlyWhenLive {
if (amount == 0) revert CommonEventsAndErrors.ExpectedNonZero();
+ uint256 _bidTokenAmountBefore = IERC20(bidToken).balanceOf(treasury);
bidToken.safeTransferFrom(msg.sender, treasury, amount);
+ uint256 _bidTokenAmountAfter = IERC20(bidToken).balanceOf(treasury);
+ uint256 _actualAmount = _bidTokenAmountAfter - _bidTokenAmountBefore;
uint256 epochIdCache = _currentEpochId;
- depositors[msg.sender][epochIdCache] += amount;
+ depositors[msg.sender][epochIdCache] += _actualAmount;
EpochInfo storage info = epochs[epochIdCache];
- info.totalBidTokenAmount += amount;
+ info.totalBidTokenAmount += _actualAmount;
- emit Deposit(msg.sender, epochIdCache, amount);
+ emit Deposit(msg.sender, epochIdCache, _actualAmount);
}
If you don't want to allow fee-on-transfer tokens add the following check:
+ if (amount != _actualAmount) revert CommonEventsAndErrors.InvalidParam();