Summary
An internal function _canDistribute()
invoked within TempleGold::mint()
implements flawed logic that allows minting tokens beyond the maximum supply.
Vulnerability Details
TempleGold::mint()
invokes the internal function _canDistribute()
, which is supposed to control the minted supply.
TempleGold::mint()
function mint() external override onlyArbitrum {
VestingFactor memory vestingFactorCache = vestingFactor;
DistributionParams storage distributionParamsCache = distributionParams;
if (vestingFactorCache.numerator == 0) { revert ITempleGold.MissingParameter(); }
uint256 mintAmount = _getMintAmount(vestingFactorCache);
if (!_canDistribute(mintAmount)) { return; }
lastMintTimestamp = uint32(block.timestamp);
_distribute(distributionParamsCache, mintAmount);
}
However, _canDistribute()
has flawed logic, particularly in its return statement.
_canDistribute()
function _canDistribute(uint256 mintAmount) private view returns (bool) {
return mintAmount != 0 && _totalDistributed + mintAmount == MAX_SUPPLY ? true : mintAmount >= MINIMUM_MINT;
}
The return statement will return true if mintAmount >= MINIMUM_MINT
, effectively allowing mint amounts greater than MINIMUM_MINT
to bypass the conditions imposed earlier _totalDistributed + mintAmount == MAX_SUPPLY
. This is the flaw in the logic.
Now reviewing the code again of TempleGold::mint()
, this allows the minting more than the maximum supply via internal function _distribute()
.
TempleGold::mint()
function mint() external override onlyArbitrum {
VestingFactor memory vestingFactorCache = vestingFactor;
DistributionParams storage distributionParamsCache = distributionParams;
if (vestingFactorCache.numerator == 0) { revert ITempleGold.MissingParameter(); }
uint256 mintAmount = _getMintAmount(vestingFactorCache);
if (!_canDistribute(mintAmount)) { return; }
lastMintTimestamp = uint32(block.timestamp);
_distribute(distributionParamsCache, mintAmount);
}
Impact
Minting more than the intended maximum supply can lead to inflationary effects, devaluation, and eventual loss of value.
Tools Used
Manual Review
Recommendations
Make a simple fix in _canDistribute()
like this:
function _canDistribute(uint256 mintAmount) private view returns (bool) {
- return mintAmount != 0 && _totalDistributed + mintAmount == MAX_SUPPLY ? true : mintAmount >= MINIMUM_MINT;
+ return mintAmount >= MINIMUM_MINT && _totalDistributed + mintAmount == MAX_SUPPLY ? true : false;
}