TempleGold

TempleDAO
Foundry
25,000 USDC
View results
Submission Details
Severity: medium
Invalid

`DAIGoldAuction` allocation of `templeGold` token are lost each time the tokens are transferred out in `recoverToken` function.

Summary

DAIGoldAuction is allocated 70% of templeGold token, minted to the contract by templeGold token contract (TempleGold.s0l) over the period of 3 years. This allocation is gradually sent to the DAIGoldAuction contract time to time and stored in nextAuctionGoldAmount.

However, anytime templeGold tokens are recovered from an auction in auctionStartCooldown period and transferred out of DAIGoldAuction.sol, these tokens sent out essentially become a loss for the DAIGoldAuction contract due to the fact that the only way DAIGoldAuction contract recieves allocation for auctions is from the templeGold token contract (stored in nextAuctionGoldAmount). Therefore there is no viable way to return any recovered templeGold tokens that are transferred out of the DAIGoldAuction contract which subsequently becomes a loss and reduces the DAIGoldAuction allocation.

Vulnerability Details

recoverToken function on DAIGoldAuction.sol allows an authorized admin to recover a specified amount of a token to a given address. The function differentiates between an arbitary token and templeGold token, with additional logic for handling the recovery of templeGold token. For templeGold token recovery, recoverToken function checks to ensure that current epoch is valid and not currently active or already ended (i.e in auctionStartCooldown period) while also ensuring that the specified amount to be recovered does not exceed the total supply auction amount of the epoch (note: admin can specify to recover the total auction amount for epoch if that's the requirement). The EpochInfo is then deleted and the specified amount is sent to the given address and any leftover amount is added to nextAuctionGoldAmount.

https://github.com/Cyfrin/2024-07-templegold/blob/57a3e597e9199f9e9e0c26aab2123332eb19cc28/protocol/contracts/templegold/DaiGoldAuction.sol#L260-L294
https://github.com/Cyfrin/2024-07-templegold/blob/57a3e597e9199f9e9e0c26aab2123332eb19cc28/protocol/contracts/templegold/DaiGoldAuction.sol#L293

However, each time templeGold tokens are recovered from an auction in auctionStartCooldown period and transferred out of the DAIGoldAuction contract, these tokens sent out essentially become a loss for the DAIGoldAuction contract. This is because the only way DAIGoldAuction contract recieves allocation for auctions is from the templeGold token contract (stored in nextAuctionGoldAmount when notifyDistribution function is called), with no other viable way to return any recovered templeGold tokens that are transferred out of the DAIGoldAuction contract (even if there were to be transferred back into the DAIGoldAuction contract).

https://github.com/Cyfrin/2024-07-templegold/blob/57a3e597e9199f9e9e0c26aab2123332eb19cc28/protocol/contracts/templegold/DaiGoldAuction.sol#L167-L176
https://github.com/Cyfrin/2024-07-templegold/blob/57a3e597e9199f9e9e0c26aab2123332eb19cc28/protocol/contracts/templegold/DaiGoldAuction.sol#L174

This execution reduces DAIGoldAuction allocation because these recovered templeGold tokens become lost tokens for DAIGoldAuction.sol (as far as DAIGoldAuction contract is concerned) which is not ideal since allocation sent to DAIGoldAuction.sol from templeGold token contract are strict allocations for DAI auctions.

Impact

Recovered templeGold token become a loss for DAIGoldAuction.sol and reduces DAIGoldAuction allocation.

POC

Run test in DaiGoldAuction.t.sol with command forge test --match-test test_recoverToken_daiGold_POC -vvv.

function test_recoverToken_daiGold_POC() public {
_setVestingFactor(templeGold);
skip(1 days);
vm.startPrank(executor);
IDaiGoldAuction.AuctionConfig memory _config = _getAuctionConfig();
daiGoldAuction.setAuctionConfig(_config);
_startAuction();
IAuctionBase.EpochInfo memory info = daiGoldAuction.getEpochInfo(1);
// cooldown time
vm.warp(info.startTime - 10 seconds);
// recover full amount of TGLD
uint256 recoverAmount = info.totalAuctionTokenAmount;
daiGoldAuction.recoverToken(address(templeGold), teamGnosis, recoverAmount);
vm.stopPrank();
// transfer back recovered amount to use for next epoch
vm.startPrank(teamGnosis);
templeGold.transfer(address(daiGoldAuction), recoverAmount);
uint256 nextAuctionGoldAmount = daiGoldAuction.nextAuctionGoldAmount();
// transferrring back doesn't mean we can use for next epoch (only minted TGLD can be used
// for next epoch or auction) therefore these tokens become useless towards DAIAuction.
assertEq(nextAuctionGoldAmount, 0);
}

Tools Used

Manual

Recommendations

Allow Elevated Access to call notifyDistribution function to return recovered tokens back to DAIGoldAuction.sol.

function notifyDistribution(uint256 amount) external override {
- if (msg.sender != address(templeGold)) { revert CommonEventsAndErrors.InvalidAccess(); }
+ if (msg.sender != address(templeGold) && !isElevatedAccess(msg.sender, msg.sig)) {revert CommonEventsAndErrors.InvalidAccess();}
/// @notice Temple Gold contract mints TGLD amount to contract before calling `notifyDistribution`
nextAuctionGoldAmount += amount;
emit GoldDistributionNotified(amount, block.timestamp);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Appeal created

superman_i4g Submitter
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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