updatePeriod() less mint HERMES
mediumLines of code
Vulnerability details
Impact
If there is a weekly that has not been taken, it may result in insufficient mint HERMES
Proof of Concept
In updatePeriod(), mint new HERMES every week with a certain percentage weeklyEmission.
The code is as follows.
solidityfunction updatePeriod() public returns (uint256) { uint256 _period = activePeriod; // only trigger if new week if (block.timestamp >= _period + week && initializer == address(0)) { _period = (block.timestamp / week) * week; activePeriod = _period; uint256 newWeeklyEmission = weeklyEmission(); @> weekly += newWeeklyEmission; uint256 _circulatingSupply = circulatingSupply(); uint256 _growth = calculateGrowth(newWeeklyEmission); uint256 _required = _growth + newWeeklyEmission; /// @dev share of newWeeklyEmission emissions sent to DAO. uint256 share = (_required * daoShare) / base; _required += share; uint256 _balanceOf = underlying.balanceOf(address(this)); @> if (_balanceOf < _required) { HERMES(underlying).mint(address(this), _required - _balanceOf); } underlying.safeTransfer(address(vault), _growth); if (dao != address(0)) underlying.safeTransfer(dao, share); emit Mint(msg.sender, newWeeklyEmission, _circulatingSupply, _growth, share); /// @dev queue rewards for the cycle, anyone can call if fails /// queueRewardsForCycle will call this function but won't enter /// here because activePeriod was updated try flywheelGaugeRewards.queueRewardsForCycle() {} catch {} } return _period; }
The above code will first determine if the balance of the current contract is less than _required and if it is less, then mint new HERMES, so that there will be enough HERMES for the distribution.
But there is a problem that the current balance of contract may contain the last weekly HERMES,that flywheelGaugeRewards have not yet been taken: (e.g. last week's allocation of weeklyEmission)
Because the gaugeCycle of flywheelGaugeRewards may be greater than one week. So it is possible that the last weekly HERMES has not yet been taken.
So we can't use the current balance to compare with _required directly, we need to Consider the weekly staying in the contract, it hasn't been taken, to avoid not having enough balance when flywheelGaugeRewards comes to take weekly.
Tools Used
Recommended Mitigation Steps
solidityfunction updatePeriod() public returns (uint256) { uint256 _period = activePeriod; // only trigger if new week if (block.timestamp >= _period + week && initializer == address(0)) { _period = (block.timestamp / week) * week; activePeriod = _period; uint256 newWeeklyEmission = weeklyEmission(); weekly += newWeeklyEmission; uint256 _circulatingSupply = circulatingSupply(); uint256 _growth = calculateGrowth(newWeeklyEmission); uint256 _required = _growth + newWeeklyEmission; /// @dev share of newWeeklyEmission emissions sent to DAO. uint256 share = (_required * daoShare) / base; _required += share; uint256 _balanceOf = underlying.balanceOf(address(this)); - if (_balanceOf < _required) { + if (_balanceOf < weekly + _growth + share ) { - HERMES(underlying).mint(address(this), _required - _balanceOf); + HERMES(underlying).mint(address(this),weekly + _growth + share - _balanceOf); } underlying.safeTransfer(address(vault), _growth); if (dao != address(0)) underlying.safeTransfer(dao, share); emit Mint(msg.sender, newWeeklyEmission, _circulatingSupply, _growth, share); /// @dev queue rewards for the cycle, anyone can call if fails /// queueRewardsForCycle will call this function but won't enter /// here because activePeriod was updated try flywheelGaugeRewards.queueRewardsForCycle() {} catch {} } return _period; }
Assessed type
Context
