TempleGold

TempleDAO
Foundry
25,000 USDC
View results
Submission Details
Severity: low
Valid

TGLD will stuck forever for particular epoch in `DaiGoldAuction` if no bid is made

Summary

If no bid is made by users, allocated TGLD for that epoch will stuck forever and cannot be claimed. It will be rare scenerio but there should be way to recover TGLD for this.

Relevant links -
https://github.com/Cyfrin/2024-07-templegold/blob/main/protocol/contracts/templegold/DaiGoldAuction.sol

Vulnerability Details

DaiGoldAuction auction contract set X amount when auction start for particular epoch. As shown below.

function startAuction() external override {
if (auctionStarter != address(0) && msg.sender != auctionStarter) { revert CommonEventsAndErrors.InvalidAccess(); }
EpochInfo storage prevAuctionInfo = epochs[_currentEpochId];
if (!prevAuctionInfo.hasEnded()) { revert CannotStartAuction(); }
AuctionConfig storage config = auctionConfig;
/// @notice last auction end time plus wait period
if (_currentEpochId > 0 && (prevAuctionInfo.endTime + config.auctionsTimeDiff > block.timestamp)) {
revert CannotStartAuction();
}
_distributeGold();
@> uint256 totalGoldAmount = nextAuctionGoldAmount;
nextAuctionGoldAmount = 0;
@> uint256 epochId = _currentEpochId = _currentEpochId + 1;
if (totalGoldAmount < config.auctionMinimumDistributedGold) { revert LowGoldDistributed(totalGoldAmount); }
EpochInfo storage info = epochs[epochId];
@> info.totalAuctionTokenAmount = totalGoldAmount;
uint128 startTime = info.startTime = uint128(block.timestamp) + config.auctionStartCooldown;
uint128 endTime = info.endTime = startTime + AUCTION_DURATION;
emit AuctionStarted(epochId, msg.sender, startTime, endTime, totalGoldAmount);
}

As highlighted above, particular amount is set for given epoch when auction begins. If auction has no bid, contract has no mechanism to recover the particular amount.

Current recover token mechanism only allow recovering TGLD before auction starts, check the highlighted code below-

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;
}
// auction started but cooldown pending
uint256 epochId = _currentEpochId;
EpochInfo storage info = epochs[epochId];
if (info.startTime == 0) { revert InvalidOperation(); }
/// recover TGLD only when current epoch is in waiting period
@> if (info.isActive()) { revert AuctionActive(); }
@> if (info.hasEnded()) { revert AuctionEnded(); }
uint256 _totalAuctionTokenAmount = info.totalAuctionTokenAmount;
if (amount > _totalAuctionTokenAmount) { revert CommonEventsAndErrors.InvalidAmount(token, amount); }
/// @dev Epoch data is deleted and leftover amount is addedd to nextAuctionGoldAmount.
/// so admin should recover total auction amount for epoch if that's the requirement
delete epochs[epochId];
/// @dev `nextAuctionGoldAmount` is set to 0 in `startAuction`.
/// `nextAuctionGoldAmount > 0` if there was a distribution after `auctionStart` called
/// epoch is deleted. so if amount < totalAuctionTokenAmount for epoch, add leftover to next auction amount
unchecked {
nextAuctionGoldAmount += _totalAuctionTokenAmount - amount;
}
emit CommonEventsAndErrors.TokenRecovered(to, token, amount);
templeGold.safeTransfer(to, amount);
}

Impact

Although this will be rare scenario, lack of recover mechanism will be loss of funds to the protocol.

Tools Used

Manual Review

Recommendations

Add a recover mechanism to handle this edge case.

function recoverTokenFromZeroBidAuction(uint256 epoch, address to) external onlyElevatedAccess {
uint256 currentId = _currentEpochId;
/// make sure epoch is in past
if(epoch >= currentId) {revert InvalidOperation();}
EpochInfo storage info = epochs[epochId];
/// don't allow TGLD Claim if there is greater than zero bid amount
if(info.totalBidTokenAmount !=0 ){ revert InvalidOperation();}
uint256 claimAmount = info.totalAuctionTokenAmount;
info.totalAuctionTokenAmount = 0;
templeGold.safeTransfer(to, claimAmount);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Auctioned tokens cannot be recovered for epochs with empty bids in DaiGoldAuction

Support

FAQs

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