[G-01] No need to initialize variables with default values
Impact
If a variable is not set/initialized, it is assumed to have the default value (0, false, 0x0 etc depending on the data type). Explicitly initializing it with its default value is an anti-pattern and wastes gas.
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public queuedRewards = 0;
uint256 public currentRewards = 0;
uint256 public historicalRewards = 0;
BaseRewardPool.sol::176 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::199 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::218 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::245 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::282 => for (uint256 i = 0; i < extraRewards.length; i++) {
Booster.sol::110 => isShutdown = false;
Booster.sol::329 => for (uint256 i = 0; i < poolInfo.length; i++) {
VE3DRewardPool.sol::148 => for (uint256 i = 0; i < rewardTokens.length(); i++) {
VE3DRewardPool.sol::214 => for (uint256 i = 0; i < length; i++) {
VE3DRewardPool.sol::238 => for (uint256 i = 0; i < length; i++) {
VE3DRewardPool.sol::257 => for (uint256 i = 0; i < length; i++) {
VE3DRewardPool.sol::281 => for (uint256 i = 0; i < rewardTokens.length(); i++) {
VE3DRewardPool.sol::326 => for (uint256 i = 0; i < length; i++) {
VoterProxy.sol::217 => for (uint256 i = 0; i < _tokenVote.length; i++) {
VoterProxy.sol::227 => uint256 _balance = 0;
Recommendation
Remove explicit default initializations.
[G-02] Use != 0 instead of > 0 for Unsigned Integer Comparison in require statements.
Impact
!= 0 is cheapear than > 0 when comparing unsigned integers in require statements.
Reading array length at each iteration of the loop takes 6 gas (3 for mload and 3 to place memory_offset) in the stack. Caching the array length in the stack saves around 3 gas per iteration.
Proof of Concept
BaseRewardPool.sol::176 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::199 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::218 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::245 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::282 => for (uint256 i = 0; i < extraRewards.length; i++) {
Booster.sol::329 => for (uint256 i = 0; i < poolInfo.length; i++) {
VE3DRewardPool.sol::148 => for (uint256 i = 0; i < rewardTokens.length(); i++) {
VE3DRewardPool.sol::281 => for (uint256 i = 0; i < rewardTokens.length(); i++) {
VoterProxy.sol::217 => for (uint256 i = 0; i < _tokenVote.length; i++) {
Recommendation
Store the array’s length in a variable before the for-loop.
[G-04] ++i costs less gas compared to i++ or i += 1
Impact
++i costs less gas compared to i++ or i += 1 for unsigned integer, as pre-increment is cheaper (about 5 gas per iteration). This statement is true even with the optimizer enabled.
Proof of Concept
BaseRewardPool.sol::176 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::199 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::218 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::245 => for (uint256 i = 0; i < extraRewards.length; i++) {
BaseRewardPool.sol::282 => for (uint256 i = 0; i < extraRewards.length; i++) {
Booster.sol::329 => for (uint256 i = 0; i < poolInfo.length; i++) {
VE3DRewardPool.sol::148 => for (uint256 i = 0; i < rewardTokens.length(); i++) {
VE3DRewardPool.sol::214 => for (uint256 i = 0; i < length; i++) {
VE3DRewardPool.sol::238 => for (uint256 i = 0; i < length; i++) {
VE3DRewardPool.sol::257 => for (uint256 i = 0; i < length; i++) {
VE3DRewardPool.sol::281 => for (uint256 i = 0; i < rewardTokens.length(); i++) {
VE3DRewardPool.sol::326 => for (uint256 i = 0; i < length; i++) {
VoterProxy.sol::217 => for (uint256 i = 0; i < _tokenVote.length; i++) {
Recommendation
Use ++i instead of i++ to increment the value of an uint variable.
Same thing for --i and i--.
[G-05] SafeMath is unnecessary in solidity versions >0.8.0.
Impact
Arithmetic operations revert on underflow and overflow in solidity versions >0.8.0. Using SafeMath is redundant and a waste of gas.
Gas
[G-01] No need to initialize variables with default values
Impact
If a variable is not set/initialized, it is assumed to have the default value (0, false, 0x0 etc depending on the data type). Explicitly initializing it with its default value is an anti-pattern and wastes gas.
Proof of Concept
https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/BaseRewardPool.sol#L66-L72
Recommendation
Remove explicit default initializations.
[G-02] Use
!= 0
instead of> 0
for Unsigned Integer Comparison in require statements.Impact
!= 0
is cheapear than> 0
when comparing unsigned integers in require statements.Proof of Concept
Recommendation
Use
!= 0
instead of> 0
.[G-03] Cache Array Length Outside of Loop.
Impact
Reading array length at each iteration of the loop takes 6 gas (3 for mload and 3 to place memory_offset) in the stack. Caching the array length in the stack saves around 3 gas per iteration.
Proof of Concept
Recommendation
Store the array’s length in a variable before the for-loop.
[G-04]
++i
costs less gas compared toi++
ori += 1
Impact
++i
costs less gas compared toi++
ori += 1
for unsigned integer, as pre-increment is cheaper (about 5 gas per iteration). This statement is true even with the optimizer enabled.Proof of Concept
Recommendation
Use
++i
instead ofi++
to increment the value of an uint variable. Same thing for--i
andi--
.[G-05]
SafeMath
is unnecessary in solidity versions >0.8.0.Impact
Arithmetic operations revert on underflow and overflow in solidity versions >0.8.0. Using
SafeMath
is redundant and a waste of gas.Proof of Concept
https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/Booster.sol#L2-L4
https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/VeAssetDepositor.sol#L2-L4
https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/BaseRewardPool.sol#L42
https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/VE3DRewardPool.sol#L42-L43
https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/VoterProxy.sol#L2-L4
https://github.com/code-423n4/2022-05-vetoken/blob/2d7cd1f6780a9bcc8387dea8fecfbd758462c152/contracts/VeTokenMinter.sol#L8
Recommendation
Get rid of
SafeMath.sol
.Tools used
c4udit, manual, slither