Omniscia Alliance Block Audit

ThrottledExit Code Style Findings

ThrottledExit Code Style Findings

TET-01C: Data Mutability Optimization

TypeSeverityLocation
Gas OptimizationInformationalThrottledExit.sol:L16, L17, L30-L37

Description:

The setThrottleParams function is meant to sanitize the input configuration of the ThrottledExit contract and assign them to contract-level variables only once as it is invoked solely within constructors in the codebase of the project.

Example:

contracts/ThrottledExit.sol
30function setThrottleParams(uint256 _throttleRoundBlocks, uint256 _throttleRoundCap, uint256 throttleStart) internal {
31 require(_throttleRoundBlocks > 0, "setThrottle::throttle round blocks must be more than 0");
32 require(_throttleRoundCap > 0, "setThrottle::throttle round cap must be more than 0");
33 require(throttleRoundBlocks == 0 && throttleRoundCap == 0, "setThrottle::throttle parameters were already set");
34 throttleRoundBlocks = _throttleRoundBlocks;
35 throttleRoundCap = _throttleRoundCap;
36 nextAvailableExitBlock = throttleStart.add(throttleRoundBlocks);
37}

Recommendation:

As the variables are only assigned to once during derivative contract constructors, we advise that the code block within setThrottleParams is instead set to be of a constructor that performs the exact same statements, permitting the introduction of the immutable mutability specifier in the variable declarations of L16 and L17, greatly optimizing the codebase.

Alleviation:

The codebase has remained unaltered, inferring that the Alliance Block team preferred to retain the current scheme so as to not require code changes in the other segments that depend upon it.

TET-02C: Redundant Array Argument

TypeSeverityLocation
Gas OptimizationInformationalThrottledExit.sol:L39-L51

Description:

The signature of the initiateExit function accepts an array of address type variables as the second argument, however, they remain unutilized within the contract barring for the length member of the array that can be passed in as a uint256 argument.

Example:

contracts/ThrottledExit.sol
39function initiateExit(uint256 amountStaked, address[] memory _rewardsTokens, uint256[] memory _tokensOwed) virtual internal {
40 initialiseExitInfo(msg.sender, _rewardsTokens.length);
41
42 ExitInfo storage info = exitInfo[msg.sender];
43 info.exitBlock = getAvailableExitTime(amountStaked);
44 info.exitStake = info.exitStake.add(amountStaked);
45
46 for (uint256 i = 0; i < _rewardsTokens.length; i++) {
47 info.rewards[i] = info.rewards[i].add(_tokensOwed[i]);
48 }
49
50 emit ExitRequested(msg.sender, info.exitBlock);
51}

Recommendation:

We advise the omission of the array argument to optimize the gas cost involved in invoking the function.

Alleviation:

The array argument was replaced by its length directly optimizing the gas cost of this function.

TET-03C: Redundant while Loop

TypeSeverityLocation
Mathematical OperationsInformationalThrottledExit.sol:L70-L73

Description:

The linked code segment performs a while loop to attempt and identify how many throttleRoundBlocks can fit between the nextAvailableExitBlock and the current block number.

Example:

contracts/ThrottledExit.sol
68function getAvailableExitTime(uint256 exitAmount) internal returns(uint256 exitBlock) {
69 if(block.number > nextAvailableExitBlock) { // We've passed the next available block and need to readjust
70 uint i = nextAvailableExitBlock; // Using i instead of nextAvailableExitBlock to avoid SSTORE
71 while(i < block.number) { // Find the next future round
72 i = i.add(throttleRoundBlocks);
73 }
74 nextAvailableExitBlock = i;
75 nextAvailableRoundExitVolume = exitAmount; // Reset volume
76 return i;
77 } else { // We are still before the next available block
78 nextAvailableRoundExitVolume = nextAvailableRoundExitVolume.add(exitAmount); // Add volume
79 }
80
81 exitBlock = nextAvailableExitBlock;
82
83 if (nextAvailableRoundExitVolume >= throttleRoundCap) { // If cap reached
84 nextAvailableExitBlock = nextAvailableExitBlock.add(throttleRoundBlocks); // update next exit block
85 nextAvailableRoundExitVolume = 0; // Reset volume
86 }
87}

Recommendation:

Instead of conducting additions sequentially within a loop, a calculation can be performed instead optimizing the gas cost of the function. The calculation block.number - ((block.number - nextAvailableExitBlock) % throttleRoundBlocks) will yield the correct next available exit block.

Alleviation:

The segment was optimized to use a calculation instead of an iteration greatly optimizing its gas cost.