Omniscia Nuklai Audit

DistributionManager Code Style Findings

DistributionManager Code Style Findings

DMR-01C: Inefficient Loop Limit Evaluations

Description:

The linked for loops evaluate their limit inefficiently on each iteration.

Example:

contracts/distribution/DistributionManager.sol
305for (uint256 i = firstUnclaimedPayout; i < payments.length; i++) {

Recommendation:

We advise the statements within the for loop limits to be relocated outside to a local variable declaration that is consequently utilized for the evaluations to significantly reduce the codebase's gas cost. We should note the same optimization is applicable for storage reads present in those limits as they are newly read on each iteration (i.e. length members of arrays in storage).

Alleviation (fb50b5c39665f7df086b2de1fdbf93ba2d836bf9):

All referenced loop limit evaluations have been properly cached outside each for loop's code block to a dedicated local variable that is consequently utilized in their place, optimizing each loop's gas cost significantly.

DMR-02C: Loop Iterator Optimizations

Description:

The linked for loops increment / decrement their iterator "safely" due to Solidity's built - in safe arithmetics (post-0.8.X).

Example:

contracts/distribution/DistributionManager.sol
120for (uint256 i; i < tagsLength; i++) {

Recommendation:

We advise the increment / decrement operations to be performed in an unchecked code block as the last statement within each for loop to optimize their execution cost.

Alleviation (fb50b5c396):

All for loop iterator increments have been optimized, however, the for loop within DistributionManager::_claimOwnerPayouts contains a continue statement that does not increment the iterator properly causing a loop that never terminates.

We advise the unchecked increment statement to be relocated right after the collectToken assignment, ensuring the loop continues as expected while being optimal.

Alleviation (938d6b02ca):

The iterator's increment statement was relocated right after the collectToken assignment as advised, ensuring that the continue statement does not affect the loop's ability to terminate and thus applying this exhibit's optimization safely.

DMR-03C: Redundant Function Argument

Description:

The DistributionManager::_claimPayouts function is solely invoked by the DistributionManager::claimDatasetOwnerAndFragmentPayouts function which will in turn supply the ContextUpgradeable::_msgSender as the function's argument at all times.

Example:

contracts/distribution/DistributionManager.sol
369function _claimPayouts(address beneficiary) internal {
370 // Claim payouts
371 uint256 firstUnclaimedPayout = _firstUnclaimedContribution[beneficiary];
372 if (firstUnclaimedPayout >= payments.length) return; // Nothing to claim
373 _firstUnclaimedContribution[beneficiary] = payments.length; // CEI pattern to prevent reentrancy
374
375 address collectToken = payments[firstUnclaimedPayout].token;
376 uint256 collectAmount;
377 for (uint256 i = firstUnclaimedPayout; i < payments.length; i++) {
378 Payment storage p = payments[i];
379 if (collectToken != p.token) {
380 // Payment token changed, send what we've already collected
381 _sendPayout(collectToken, collectAmount, beneficiary);
382 collectToken = p.token;
383 collectAmount = 0;
384 }
385 collectAmount += _calculatePayout(p, beneficiary);
386 }
387 // send collected and not sent yet
388 _sendPayout(collectToken, collectAmount, beneficiary);
389}

Recommendation:

We advise the code to omit its input argument and to utilize the ContextUpgradeable::_msgSender value directly, optimizing its gas cost.

This will also permit the function to be invoked by the DistributionManager::claimPayouts function, reducing the overall bytecode size of the contract.

Alleviation (fb50b5c39665f7df086b2de1fdbf93ba2d836bf9):

The beneficiary argument of the DistributionManager::_claimPayouts function has been properly replaced by a local homonymous variable that is assigned with the value of ContextUpgradeable::_msgSender as advised.

DMR-04C: Repetitive Value Literals

Description:

The linked value literals are repeated across the codebase multiple times.

Example:

contracts/distribution/DistributionManager.sol
161if (percentage > 5e17) revert PERCENTAGE_VALUE_INVALID(5e17, percentage);

Recommendation:

We advise each to be set to its dedicated constant variable instead optimizing the legibility of the codebase.

Alleviation (fb50b5c39665f7df086b2de1fdbf93ba2d836bf9):

The referenced value literals 5e17, and 1e18 have all been relocated to contract-level constant declarations labelled MAX_DATASET_OWNER_PERCENTAGE, and BASE_100_PERCENT respectively, optimizing the code's legibility.