Omniscia Stakewise Audit
RewardEthToken Code Style Findings
RewardEthToken Code Style Findings
RET-01C: Duplicate Event Emittance & Storage Write
| Type | Severity | Location |
|---|---|---|
| Gas Optimization | Informational | RewardEthToken.sol:L216, L253-L259 |
Description:
The updateTotalRewards function contains a logic path via which the RewardsUpdated event is emitted twice with the same arguments and the lastUpdateBlockNumber is written twice to the same value.
Example:
contracts/tokens/RewardEthToken.sol
207/**208 * @dev See {IRewardEthToken-updateTotalRewards}.209 */210function updateTotalRewards(uint256 newTotalRewards) external override {211 require(msg.sender == oracles, "RewardEthToken: access denied");212
213 uint256 periodRewards = newTotalRewards.sub(totalRewards);214 if (periodRewards == 0) {215 lastUpdateBlockNumber = block.number;216 emit RewardsUpdated(0, newTotalRewards, rewardPerToken, 0, 0);217 }218
219 // calculate protocol reward and new reward per token amount220 uint256 protocolReward = periodRewards.mul(protocolFee).div(1e4);221 uint256 prevRewardPerToken = rewardPerToken;222 uint256 newRewardPerToken = prevRewardPerToken.add(periodRewards.sub(protocolReward).mul(1e18).div(stakedEthToken.totalDeposits()));223 uint128 newRewardPerToken128 = newRewardPerToken.toUint128();224
225 // store previous distributor rewards for period reward calculation226 uint256 prevDistributorBalance = _balanceOf(address(0), prevRewardPerToken);227
228 // update total rewards and new reward per token229 (totalRewards, rewardPerToken) = (newTotalRewards.toUint128(), newRewardPerToken128);230
231 uint256 newDistributorBalance = _balanceOf(address(0), newRewardPerToken);232 address _protocolFeeRecipient = protocolFeeRecipient;233 if (_protocolFeeRecipient == address(0) && protocolReward > 0) {234 // add protocol reward to the merkle distributor235 newDistributorBalance = newDistributorBalance.add(protocolReward);236 } else if (protocolReward > 0) {237 // update fee recipient's checkpoint and add its period reward238 checkpoints[_protocolFeeRecipient] = Checkpoint({239 reward: _balanceOf(_protocolFeeRecipient, newRewardPerToken).add(protocolReward).toUint128(),240 rewardPerToken: newRewardPerToken128241 });242 }243
244 // update distributor's checkpoint245 if (newDistributorBalance != prevDistributorBalance) {246 checkpoints[address(0)] = Checkpoint({247 reward: newDistributorBalance.toUint128(),248 rewardPerToken: newRewardPerToken128249 });250 }251
252 lastUpdateBlockNumber = block.number;253 emit RewardsUpdated(254 periodRewards,255 newTotalRewards,256 newRewardPerToken,257 newDistributorBalance.sub(prevDistributorBalance),258 _protocolFeeRecipient == address(0) ? protocolReward: 0259 );260}Recommendation:
We advise a return event to be introduced after the first emittance to ensure that the function ends early and does not waste gas executing the ensuing statements as they will be ineffectual in the case that the periodRewards are zero.
Alleviation:
A return statement was properly introduced according to our recommendation.