Omniscia Bolide Finance Audit

Storage Code Style Findings

Storage Code Style Findings

SEG-01C: Generic Typographic Mistakes

TypeSeverityLocation
Code StyleStorage.sol:L75-L87, L93, L470, L564, L625, L669, L678, L696

Description:

The referenced lines contain typographical mistakes (i.e. private variable without an underscore prefix) or generic documentational errors (i.e. copy-paste) that should be corrected.

Example:

strategies/low_risk/contracts/Storage.sol
75mapping(uint256 => EarnBLID) private earnBLID;
76uint256 private countEarns;
77uint256 private countTokens;
78mapping(uint256 => address) private tokens;
79mapping(address => uint256) private tokenBalance;
80mapping(address => address) private oracles;
81mapping(address => bool) private tokensAdd;
82mapping(address => DepositStruct) private deposits;
83mapping(address => uint256) private tokenDeposited;
84mapping(address => int256) private tokenTime;
85uint256 private reserveBLID;
86address private logicContract;
87address private BLID;

Recommendation:

We advise them to be corrected enhancing the legibility of the codebase.

Alleviation (fcd1a542d2d7b23c561a73199ec91be0a8f0a340):

The Bolide Finance team has re-styled their code to properly prefix private functions with an underscore (_), however, the public yet prefixed functions as well as the private contract variables have remained untouched. As the Bolide Finance team has stated that they plan to address these in a future version, we consider the exhibit adequately dealt with.

SEG-02C: Inefficient Loop Limit Evaluations

TypeSeverityLocation
Gas OptimizationStorage.sol:L172, L434, L452, L491, L512, L536

Description:

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

Example:

strategies/low_risk/contracts/Storage.sol
172for (uint256 i = 0; i < countEarns_; 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 (fcd1a542d2d7b23c561a73199ec91be0a8f0a340):

All referenced for loop iterators that are still applicable to the codebase have been adequately optimized in unchecked code blocks as advised.

SEG-03C: Inefficient mapping Lookups

TypeSeverityLocation
Gas OptimizationStorage.sol:L471, L472, L636, L637, L642, L783, L784

Description:

The linked statements perform key-based lookup operations on mapping declarations from storage multiple times for the same key redundantly.

Example:

strategies/low_risk/contracts/Storage.sol
635if (depositor.tokenTime[address(0)] == 0) {
636 depositor.iterate = countEarns;
637 depositor.depositIterate[token] = countEarns;
638 depositor.tokenTime[address(0)] = 1;
639 depositor.tokenTime[token] += int256(block.timestamp * (amountExp18));
640} else {
641 interestFee(accountAddress);
642 if (depositor.depositIterate[token] == countEarns) {

Recommendation:

As the lookups internally perform an expensive keccak256 operation, we advise the lookups to be cached wherever possible to a single local declaration that either holds the value of the mapping in case of primitive types or holds a storage pointer to the struct contained.

Alleviation (fcd1a542d2d7b23c561a73199ec91be0a8f0a340):

The referenced lines of code have been optimized to the fullest extent possible as advised.

SEG-04C: Inexistent Error Message

TypeSeverityLocation
Code StyleStorage.sol:L183, L445

Description:

The linked require check has no error message explicitly defined.

Example:

strategies/low_risk/contracts/Storage.sol
183require(_token != address(0) && _oracles != address(0));

Recommendation:

We advise one to be set so to increase the legibility of the codebase and aid in validating the require check's condition.

Alleviation (fcd1a542d2d7b23c561a73199ec91be0a8f0a340):

Error codes have been adequately introduced to both referenced require checks as advised.

SEG-05C: Non-Descriptive Function Name

TypeSeverityLocation
Code StyleStorage.sol:L169

Description:

The updateAccumulatedRewardsPerShare function is meant to be invoked once for a particular token which is not clearly depicted in the function's name.

Example:

strategies/low_risk/contracts/Storage.sol
169function updateAccumulatedRewardsPerShare(address token) external onlyOwner {
170 require(accumulatedRewardsPerShare[token][0] == 0, "E7");
171 uint256 countEarns_ = countEarns;
172 for (uint256 i = 0; i < countEarns_; i++) {
173 updateAccumulatedRewardsPerShareById(token, i);
174 }
175}

Recommendation:

We advise it to be renamed to initializeAccumulatedRewardsPerShare, clearly indicating that the function is meant to be invoked once for a particular token.

Alleviation (fcd1a542d2d7b23c561a73199ec91be0a8f0a340):

The function was removed from the codebase instead as it was assessed as deprecated by the Bolide Finance team, rendering this exhibit inapplicable.

SEG-06C: Redundant Unconditional Execution of Statements

TypeSeverityLocation
Gas OptimizationStorage.sol:L273-L288

Description:

The interestFee function is significantly inefficient if the balanceUser is yielded as 0.

Example:

strategies/low_risk/contracts/Storage.sol
273function interestFee(address accountAddress) public {
274 uint256 balanceUser = balanceEarnBLID(accountAddress);
275 require(reserveBLID >= balanceUser, "E5");
276 IERC20Upgradeable(BLID).safeTransfer(accountAddress, balanceUser);
277 DepositStruct storage depositor = deposits[accountAddress];
278 depositor.balanceBLID = balanceUser;
279 depositor.iterate = countEarns;
280 //unchecked is used because a check was made in require
281 unchecked {
282 depositor.balanceBLID = 0;
283 reserveBLID -= balanceUser;
284 }
285
286 emit UpdateBLIDBalance(reserveBLID);
287 emit InterestFee(accountAddress, balanceUser);
288}

Recommendation:

We advise the code to instead only update the depositor.iterate to countEarns if balanceUser is 0, avoiding the increased gas cost involved in all other operations in such a case as they are ineffectual.

Alleviation (fcd1a542d2):

The code was incorrectly optimized as our recommended course of action was not applied. We advised that the depositor.iterate is properly updated to countEarns outside the conditional evaluating the balanceUser. We strongly advise the code to be corrected as it can presently cause misbehaviours.

Alleviation (c2c03f7731):

The code was corrected per our initial recommendation, updating only the value of iterate if balanceUser evaluates to zero.

SEG-07C: Relocation of Statements

TypeSeverityLocation
Gas OptimizationStorage.sol:L240, L242-L243, L245, L247, L250

Description:

The referenced statements are performed identically in all clauses of the if structure they are located in.

Example:

strategies/low_risk/contracts/Storage.sol
238if (amountExp18 > tokenBalance[token]) {
239 ILogicContract(logicContract).returnToken(amount, token);
240 interestFee(msg.sender);
241 IERC20Upgradeable(token).safeTransferFrom(logicContract, msg.sender, amount);
242 tokenDeposited[token] -= amountExp18;
243 tokenTime[token] -= int256(block.timestamp * (amountExp18));
244} else {
245 interestFee(msg.sender);
246 IERC20Upgradeable(token).safeTransfer(msg.sender, amount);
247 tokenTime[token] -= int256(block.timestamp * (amountExp18));
248
249 tokenBalance[token] -= amountExp18;
250 tokenDeposited[token] -= amountExp18;
251}

Recommendation:

We advise them to be relocated outside the if structure, optimizing the gas cost and legibility of the codebase.

Alleviation (fcd1a542d2d7b23c561a73199ec91be0a8f0a340):

The code of withdraw was greatly simplified my relocating the common statements outside their respective conditionals as advised.

SEG-08C: Repetitive Value Literal

TypeSeverityLocation
Code StyleStorage.sol:L483, L635, L638

Description:

The linked value literal is repeated across the codebase multiple times.

Example:

strategies/low_risk/contracts/Storage.sol
483if (depositor.tokenTime[address(0)] == 0 || countEarns == 0) {

Recommendation:

We advise it to be set to a constant variable instead optimizing the legibility of the codebase.

Alleviation (fcd1a542d2d7b23c561a73199ec91be0a8f0a340):

The address(0) literal has been relocated to a contract-level constant declaration labelled as ZERO_ADDRESS, optimizing the legibility of the codebase.

SEG-09C: Variable Optimization

TypeSeverityLocation
Gas OptimizationStorage.sol:L408

Description:

The referenced statement utilizes the logicContract storage variable while having validated that the caller of the function (i.e. msg.sender) is equivalent to the said value.

Example:

strategies/low_risk/contracts/Storage.sol
401function returnToken(uint256 amount, address token)
402 external
403 isLogicContract(msg.sender)
404 isUsedToken(token)
405{
406 uint8 decimals = AggregatorV3Interface(token).decimals();
407 uint256 amountExp18 = amount * 10**(18 - decimals);
408 IERC20Upgradeable(token).safeTransferFrom(logicContract, address(this), amount);
409 tokenBalance[token] = tokenBalance[token] + amountExp18;
410
411 emit UpdateTokenBalance(tokenBalance[token], token);
412 emit ReturnToken(token, amountExp18);
413}

Recommendation:

We advise the msg.sender to be utilized directly instead, optimizing the code's gas cost.

Alleviation (fcd1a542d2d7b23c561a73199ec91be0a8f0a340):

The safeTransferFrom function execution was optimized by passing in msg.sender instead of logicContract as advised.