Summary
In the DaiGoldAuction
contract, users bid tokens might be lost if an epoch's data is deleted without a mechanism for users to reclaim their bid amounts. This issue arises in the recoverToken
function, where the epoch data is deleted, but the bid tokens associated with that epoch are not refunded to the users.
Vulnerability Details
The vulnerability is located in the recoverToken
function. When this function is called, it can delete an epoch's data without providing a way for users to recover their bid tokens for that epoch. Specifically, the function deletes the epoch data, including the totalBidTokenAmount
, without ensuring that users who participated in the auction can reclaim their bids. This can lead to a situation where users lose their funds if an epoch is deleted.
Here is the relevant code snippet:
function recoverToken(
address token,
address to,
uint256 amount
) external override onlyElevatedAccess {
if (to == address(0)) { revert CommonEventsAndErrors.InvalidAddress(); }
if (amount == 0) { revert CommonEventsAndErrors.ExpectedNonZero(); }
if (token != address(templeGold)) {
emit CommonEventsAndErrors.TokenRecovered(to, token, amount);
IERC20(token).safeTransfer(to, amount);
return;
}
uint256 epochId = _currentEpochId;
EpochInfo storage info = epochs[epochId];
if (info.startTime == 0) { revert InvalidOperation(); }
if (info.isActive()) { revert AuctionActive(); }
if (info.hasEnded()) { revert AuctionEnded(); }
uint256 _totalAuctionTokenAmount = info.totalAuctionTokenAmount;
if (amount > _totalAuctionTokenAmount) { revert CommonEventsAndErrors.InvalidAmount(token, amount); }
@> delete epochs[epochId];
unchecked {
nextAuctionGoldAmount += _totalAuctionTokenAmount - amount;
}
emit CommonEventsAndErrors.TokenRecovered(to, token, amount);
templeGold.safeTransfer(to, amount);
}
Impact
The primary impact of this vulnerability is the potential loss of user funds. If an epoch is deleted and the associated bid tokens are not refunded, users who participated in that epoch's auction will lose their bid amounts. This affects the fairness and integrity of the auction process and can lead to a loss of trust in the platform.
Tools Used
Manual Code Review
Recommendations
To mitigate this issue, the following changes are recommended:
-
Track Deleted Epochs: Maintain a mapping to store the total bid amounts for deleted epochs.
mapping(uint256 => uint256) public deletedEpochsBidAmounts;
-
Implement a Refund Function: Add a function that allows users to claim their bid amounts for deleted epochs.
function claimDeletedEpochBid(uint256 epochId) external {
uint256 bidAmount = depositors[msg.sender][epochId];
if (bidAmount == 0) {
revert CommonEventsAndErrors.ExpectedNonZero();
}
if (deletedEpochsBidAmounts[epochId] == 0) {
revert InvalidEpoch();
}
depositors[msg.sender][epochId] = 0;
bidToken.safeTransferFrom(treasury, msg.sender, bidAmount);
emit ClaimDeletedEpochBid(msg.sender, epochId, bidAmount);
}
-
Update the recoverToken
Function: Modify the recoverToken
function to record the total bid amount of a deleted epoch and allow refunds.
function recoverToken(
address token,
address to,
uint256 amount
) external override onlyElevatedAccess {
if (to == address(0)) { revert CommonEventsAndErrors.InvalidAddress(); }
if (amount == 0) { revert CommonEventsAndErrors.ExpectedNonZero(); }
if (token != address(templeGold)) {
emit CommonEventsAndErrors.TokenRecovered(to, token, amount);
IERC20(token).safeTransfer(to, amount);
return;
}
uint256 epochId = _currentEpochId;
EpochInfo storage info = epochs[epochId];
if (info.startTime == 0) { revert InvalidOperation(); }
if (info.isActive()) { revert AuctionActive(); }
if (info.hasEnded()) { revert AuctionEnded(); }
uint256 _totalAuctionTokenAmount = info.totalAuctionTokenAmount;
if (amount > _totalAuctionTokenAmount) { revert CommonEventsAndErrors.InvalidAmount(token, amount); }
deletedEpochsBidAmounts[epochId] = info.totalBidTokenAmount;
unchecked {
nextAuctionGoldAmount += _totalAuctionTokenAmount - amount;
}
delete epochs[epochId];
emit CommonEventsAndErrors.TokenRecovered(to, token, amount);
templeGold.safeTransfer(to, amount);
}
By implementing these recommendations, the contract will ensure that user funds are protected and the integrity of the auction process is maintained.