code-423n4 / 2022-07-swivel-findings

0 stars 1 forks source link

Gas Optimizations #173

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

Gas Report

Replace postfix increment (var++) with prefix increment (++var)

Using ++i costs less gas than using i++. In the context of a for-loop, gas is saved on each iteration.

The following lines of code are affected:

2022-07-swivel/Swivel/Swivel.sol:418:        i++;
2022-07-swivel/Swivel/Swivel.sol:511:        x++;
2022-07-swivel/Swivel/Swivel.sol:564:        i++;

"calldata" can be used instead of "memory" to reduce gas costs

Both memory and calldata allow a developer to manage variables within the scope of a function. memory is mutable which makes it a more flexible tool; however, it costs additional gas when compared with calldata. calldata is non-modifiable but cheaper. Therefore it is recommended to use calldata for function parameters when they will not be modified.

For more information, see the following resources: Solidity Documentation recommending the use of calldata

Solidity — Storage vs Memory vs Calldata

The following function calls can be changed to use calldata instead of memory:

2022-07-swivel/Swivel/Hash.sol:59:  function domain(string memory n, string memory version, uint256 i, address verifier) internal pure returns (bytes32) {
2022-07-swivel/Swivel/Sig.sol:38:  function splitAndRecover(bytes32 h, bytes memory sig) internal pure returns (address) {
2022-07-swivel/Swivel/Sig.sol:48:  function split(bytes memory sig) internal pure returns (uint8, bytes32, bytes32) {
2022-07-swivel/Swivel/Swivel.sol:495:  function setFee(uint16[] memory i, uint16[] memory d) external authorized(admin) returns (bool) {

Use strict less-than/greather-than comparisons rather than less-than-or-equal/greater-than-or-equal

When compiled, Solidity code using the >= or <= comparison operators in fact executes two separate checks: one for 'is-equal-to' and a second for 'is-greater-than/is-less-than'. By contrast, using > or < performs only one check. Therefore code that is written to use strict comparison operators is more gas-efficient.

If this change is applied, be sure to update the relevant variables being evaluated. For clarity, it is also advised to rename the variables to make this change explicit, e.g. renaming a variable from MINIMUM to MINIMUM_PLUS_ONE.

The following lines are affected:

2022-07-swivel/Creator/FixedPointMathLib.sol:47:            if (x <= -42139678854452767551) return 0;
2022-07-swivel/Creator/FixedPointMathLib.sol:51:            if (x >= 135305999368893231589) revert ExpOverflow();
2022-07-swivel/Creator/LibCompound.sol:28:        require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH"); // Same as borrowRateMaxMantissa in CTokenInterfaces.sol
2022-07-swivel/Creator/ZcToken.sol:112:            if (allowed >= previewAmount) {
2022-07-swivel/Creator/ZcToken.sol:133:            if (allowed >= principalAmount) { revert Approvals(allowed, principalAmount); }
2022-07-swivel/Marketplace/FixedPointMathLib.sol:47:            if (x <= -42139678854452767551) return 0;
2022-07-swivel/Marketplace/FixedPointMathLib.sol:51:            if (x >= 135305999368893231589) revert ExpOverflow();
2022-07-swivel/Marketplace/LibFuse.sol:39:            if(borrowRateMantissa <= 0.0005e16) { revert RATE(); }
2022-07-swivel/Swivel/Swivel.sol:712:      return IYearn(c).deposit(a) >= 0;
2022-07-swivel/Swivel/Swivel.sol:727:      return IErc4626(c).deposit(a, address(this)) >= 0;
2022-07-swivel/Swivel/Swivel.sol:745:      return IYearn(c).withdraw(a) >= 0;
2022-07-swivel/Swivel/Swivel.sol:749:      return IAave(aaveAddr).withdraw(u, a, address(this)) >= 0;
2022-07-swivel/Swivel/Swivel.sol:757:      return IErc4626(c).withdraw(a, address(this), address(this)) >= 0;
2022-07-swivel/Tokens/FixedPointMathLib.sol:47:            if (x <= -42139678854452767551) return 0;
2022-07-swivel/Tokens/FixedPointMathLib.sol:51:            if (x >= 135305999368893231589) revert ExpOverflow();
2022-07-swivel/Tokens/LibCompound.sol:28:        require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH"); // Same as borrowRateMaxMantissa in CTokenInterfaces.sol
2022-07-swivel/Tokens/LibFuse.sol:36:            require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH");
2022-07-swivel/Tokens/ZcToken.sol:133:            if (allowed >= principalAmount) { revert Approvals(allowed, principalAmount); }
2022-07-swivel/VaultTracker/FixedPointMathLib.sol:46:            // x <= floor(log(0.5e18) * 1e18) ~ -42e18
2022-07-swivel/VaultTracker/FixedPointMathLib.sol:50:            // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.
2022-07-swivel/VaultTracker/FixedPointMathLib.sol:51:            if (x >= 135305999368893231589) revert ExpOverflow();
2022-07-swivel/VaultTracker/LibCompound.sol:28:        require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH"); // Same as borrowRateMaxMantissa in CTokenInterfaces.sol
2022-07-swivel/VaultTracker/LibFuse.sol:36:            require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH");

Pragma statement should be at least 0.8.4

The pragma declaration allows for Solidity versions less than version 0.8.4. Several gas optimization features have been introduced in versions of Solidity between 0.8.0 and 0.8.4, including:

Please note that Solidity version 0.8.9 contains bugfixes in addition to these gas improvements and that if possible it is advised to use versions greater than or equal to 0.8.9 for additional benefit.

For more information consult the following resources:

The following pragma statements should be updated:

2022-07-swivel/Creator/Erc20.sol:4:pragma solidity ^0.8.0;
2022-07-swivel/Creator/IERC5095.sol:2:pragma solidity ^0.8.0;
2022-07-swivel/Creator/IRedeemer.sol:2:pragma solidity ^0.8.0;
2022-07-swivel/Marketplace/Erc20.sol:4:pragma solidity ^0.8.0;
2022-07-swivel/Tokens/Erc20.sol:4:pragma solidity ^0.8.0;
2022-07-swivel/Tokens/IERC5095.sol:2:pragma solidity ^0.8.0;
2022-07-swivel/Tokens/IRedeemer.sol:2:pragma solidity ^0.8.0;