Omniscia Alliance Block Audit

LiquidityMiningCampaignFactory Code Style Findings

LiquidityMiningCampaignFactory Code Style Findings

LMF-01C: Data Location Optimization

Description:

The deploy function contains two dynamic array arguments that are stored in memory and is declared as external. The extendRewardPool function contains a single dynamic array argument stored in memory and is declared external as well

Example:

contracts/LiquidityMiningCampaignFactory.sol
34function deploy(
35 address _stakingToken,
36 uint256 _startBlock,
37 uint256 _endBlock,
38 address[] memory _rewardsTokens,
39 uint256[] memory _rewardPerBlock,
40 uint256 _stakeLimit
41) external onlyOwner {

Recommendation:

We advise that the data location the arrays are stored in is changed to calldata to optimize the gas cost of the code segments.

Alleviation:

The data location specifiers of the linked external function arguments was properly adjusted to calldata.

LMF-02C: Redundant Usage of SafeMath

Description:

The linked safeTransfer invocation passes in the result of a SafeMath subtraction between the variables newRemainingReward and currentRemainingReward whereas the whole statement is included within an if clause that ensures newRemainingReward is strictly greater-than currentRemainingReward.

Example:

contracts/LiquidityMiningCampaignFactory.sol
113for (uint256 i = 0; i < _rewardsPerBlock.length; i++) {
114 uint256 currentRemainingReward = calculateRewardsAmount(block.number, currentEndBlock, pool.rewardPerBlock(i));
115 uint256 newRemainingReward = calculateRewardsAmount(block.number, _endBlock, _rewardsPerBlock[i]);
116
117 address rewardsToken = RewardsPoolBase(_rewardsPoolAddress).rewardsTokens(i);
118
119 if (newRemainingReward > currentRemainingReward) {
120 // Some more reward needs to be transferred to the rewards pool contract
121 IERC20Detailed(rewardsToken).safeTransfer(_rewardsPoolAddress, newRemainingReward.sub(currentRemainingReward));
122 }
123}

Recommendation:

We advise that the sub invocation is safely omitted as the subtraction is guaranteed to never underflow, optimizing the gas cost of the function.

Alleviation:

The sub invocation was properly replaced by a raw subtraction.

LMF-03C: Redundant Validation Loop

Description:

Within Solidity gas costs are of great concern and as such code should be developed as optimal as possible. The linked for loop validates the input _rewardsTokens and _rewardPerBlock prior to their utilization in the ensuing for loop of L82-L93 redundantly so.

Example:

contracts/LiquidityMiningCampaignFactory.sol
55for (uint256 i = 0; i < _rewardsTokens.length; i++) {
56 require(
57 _rewardsTokens[i] != address(0),
58 "LiquidityMiningCampaignFactory::deploy: Reward token address could not be invalid"
59 );
60 require(
61 _rewardPerBlock[i] != 0,
62 "LiquidityMiningCampaignFactory::deploy: Reward per block must be greater than zero"
63 );
64}
65 require(
66 _stakeLimit != 0,
67 "LiquidityMiningCampaignFactory::deploy: Stake limit must be more than 0"
68);
69
70address rewardsPoolBase =
71 address(
72 new LiquidityMiningCampaign(
73 IERC20Detailed(_stakingToken),
74 _startBlock,
75 _endBlock,
76 _rewardsTokens,
77 _rewardPerBlock,
78 _stakeLimit
79 )
80 );
81
82for (uint256 i = 0; i < _rewardsTokens.length; i++) {
83 uint256 rewardsAmount =
84 calculateRewardsAmount(
85 _startBlock,
86 _endBlock,
87 _rewardPerBlock[i]
88 );
89 IERC20Detailed(_rewardsTokens[i]).safeTransfer(
90 rewardsPoolBase,
91 rewardsAmount
92 );
93}

Recommendation:

We advise that the validation is performed directly on the for loop that utilizes the variables so as to reduce the gas cost involved in utilizing the function.

Alleviation:

The validation loop was properly removed from the codebase.