TempleGold

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

The validation is missing to check the case that the sum of the `_totalDistributed` and a given `mintAmount` exceed the `MAX_SUPPLY` (`_totalDistributed + mintAmount > MAX_SUPPLY `)

Summary

The validation in the TempleGold#_canDistribute() does not consider the case that the sum of the _totalDistributed and a given mintAmount exceed the MAX_SUPPLY (_totalDistributed + mintAmount > MAX_SUPPLY ), which lead to the validation of the TempleGold#_canDistribute() can be meaningless

Vulnerability Details

Within the TempleGold contract, the MAX_SUPPLY would be defined as 1_000_000_000 ether (1 billion) like this:
https://github.com/Cyfrin/2024-07-templegold/blob/main/protocol/contracts/templegold/TempleGold.sol#L47

/// @notice 1B max supply
uint256 public constant MAX_SUPPLY = 1_000_000_000 ether; // 1B

Within the TempleGold#mint(), the TempleGold#_canDistribute() would be called.
If false is returned from the TempleGold#_canDistribute(), the whole TX would be forced to be stopped (returned) like this:
https://github.com/Cyfrin/2024-07-templegold/blob/main/protocol/contracts/templegold/TempleGold.sol#L151

function mint() external override onlyArbitrum {
...
if (!_canDistribute(mintAmount)) { return; } ///<----------- @audit

Within the TempleGold#_canDistribute(), there is the validation to check whether or not the sum of the _totalDistributed and a given mintAmount is equal to the MAX_SUPPLY (_totalDistributed + mintAmount == MAX_SUPPLY) like this:
https://github.com/Cyfrin/2024-07-templegold/blob/main/protocol/contracts/templegold/TempleGold.sol#L189

function _canDistribute(uint256 mintAmount) private view returns (bool) {
return mintAmount != 0 && _totalDistributed + mintAmount == MAX_SUPPLY ? true : mintAmount >= MINIMUM_MINT; ///<-------------- @audit
}

Within the TempleGold#_canDistribute() above, the validation in the TempleGold#_canDistribute() is supposed to check whether or not the sum of the _totalDistributed and a given mintAmount does not exceed the MAX_SUPPLY (_totalDistributed + mintAmount <= MAX_SUPPLY).

However, within the TempleGold#_canDistribute() above, the validation only consider the case that the sum of the _totalDistributed and a given mintAmount exact same with the MAX_SUPPLY (_totalDistributed + mintAmount == MAX_SUPPLY).

This lead to that this validation in the TempleGold#_canDistribute() can be meaningless - if the case that the sum of the _totalDistributed and a given mintAmount exceed the MAX_SUPPLY (_totalDistributed + mintAmount > MAX_SUPPLY ) would happen.

Exploit scenario

Let's say, at this point, the _totalDistributed would be increased to 999_999_500 ether,

  • 1/ The TempleGold#mint() would be called via the DaiGoldAuction#distributeGold() or the DaiGoldAuction#startAuction().

    • At this point, let's say 600 ether is newly minted as a mintAmount.

  • 2/ Now, the _totalDistributed has become 1_000_000_100 ether (999_999_500 ether + 600 ether).

    • This means that the _totalDistributed (1_000_000_100 ether) has exceeded the MAX_SUPPLY (1_000_000_000 ether).

    • In this case (_totalDistributed > MAX_SUPPLY), the TX (which include the TempleGold#mint()) is supposed to be stopped (returned) inside the validation of the TempleGold#_canDistribute() like below:

function _canDistribute(uint256 mintAmount) private view returns (bool) {
return mintAmount != 0 && _totalDistributed + mintAmount == MAX_SUPPLY ? true : mintAmount >= MINIMUM_MINT;
}
  • 3/ However, since only the case that the _totalDistributed and the MAX_SUPPLY are "exact" same (_totalDistributed == MAX_SUPPLY) would be considered, the TX (which include the TempleGold#mint()) would not be stopped (returned) inside the validation of the TempleGold#_canDistribute() above.

In addition to that, once the _totalDistributed exceed the MAX_SUPPLY (_totalDistributed == MAX_SUPPLY), the TX (which include the TempleGold#mint()) would never be stopped (returned) inside the validation of the TempleGold#_canDistribute().

This means that the validation of the TempleGold#_canDistribute() can be meaningless - once the _totalDistributed exceed the MAX_SUPPLY (_totalDistributed == MAX_SUPPLY).

Impact

The validation of the TempleGold#_canDistribute() can be meaningless - once the sum of the _totalDistributed and a given mintAmount exceed the MAX_SUPPLY (_totalDistributed + mintAmount > MAX_SUPPLY ) and allow the sum of the _totalDistributed + mintAmount to exceed the MAX_SUPPLY`.

Tools Used

  • Hardhat

Recommendations

Within the TempleGold#_canDistribute(), consider checking the case whether or not the sum of the _totalDistributed and a given mintAmount exceed the MAX_SUPPLY (_totalDistributed + mintAmount > MAX_SUPPLY ) to the validation like this:

function _canDistribute(uint256 mintAmount) private view returns (bool) {
+ return mintAmount != 0 && _totalDistributed + mintAmount <= MAX_SUPPLY ? true : mintAmount >= MINIMUM_MINT;
- return mintAmount != 0 && _totalDistributed + mintAmount == MAX_SUPPLY ? true : mintAmount >= MINIMUM_MINT;
}
Updates

Lead Judging Commences

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

`_canDistribute` could return a result breaking the MAX TOTAL SUPPLY of TGLD

Support

FAQs

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