Summary
TempleGold::circulatingSupply() function is supposed, according to the natSpec, to return the circulating supply of each chain, except when called on Arbitrum, which then returns the circulating supply across all chains. But this is not the case.
* @notice Get circulating supply on this chain
* @dev When this function is called on source chain (arbitrum), you get the real circulating supply across chains
* @return Circulating supply
*/
function circulatingSupply() public view override returns (uint256) {
return _totalDistributed;
}
Vulnerability Details
Calling TempleGold::circulatingSupply() in any chain apart from Arbitrum will always return 0. The function returns _totalDistributed which is only updated during minting/distributing of tokens, which is only possible to happen in the Arbitrum chain.
uint256 private _totalDistributed;
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);
}
function _distribute(DistributionParams storage params, uint256 mintAmount) private {
uint256 stakingAmount = TempleMath.mulDivRound(params.staking, mintAmount, DISTRIBUTION_DIVISOR, false);
if (stakingAmount > 0) {
.
.
.
@> _totalDistributed += mintAmount;
emit Distributed(stakingAmount, escrowAmount, gnosisAmount, block.timestamp);
}
Impact
The function doesn't work as expected and will always return wrong results.
Tools Used
Manuel Review
Recommendations
If not on Arbitrum chain, make the TempleGold::circulatingSupply() function to return the totalSupply() of the token.