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

0 stars 1 forks source link

Gas Optimizations #147

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

1. Use calldata instead of memory

Use calldata instead of memory to save gas. See here for reference: https://code4rena.com/reports/2022-04-badger-citadel/#g-12-stakedcitadeldepositall-use-calldata-instead-of-memory

Instances:

Link: https://github.com/code-423n4/2022-07-swivel/blob/main/Swivel/Swivel.sol#L495

Swivel/Swivel.sol:495:  function setFee(uint16[] memory i, uint16[] memory d) external authorized(admin) returns (bool) {


2. Custom Errors instead of Revert Strings to save Gas

Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met)

Starting from Solidity v0.8.4,there is a convenient and gas-efficient way to explain to users why an operation failed through the use of custom errors. Until now, you could already use strings to give more information about failures (e.g., revert("Insufficient funds.");),but they are rather expensive, especially when it comes to deploy cost, and it is difficult to use dynamic information in them.

Custom errors are defined using the error statement, which can be used inside and outside of contracts (including interfaces and libraries).

Instances Includes:

Links: Creator/LibFuse.sol:36 VaultTracker/LibFuse.sol:36 Tokens/LibFuse.sol:36

Creator/LibFuse.sol:36:            require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH");
VaultTracker/LibFuse.sol:36:            require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH");
Tokens/LibFuse.sol:36:            require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH");

References:

https://blog.soliditylang.org/2021/04/21/custom-errors/

Remediation:

I suggest replacing revert strings with custom errors.



Preincrement costs less gas as compared to Postincrement :

++i costs less gas as compared to i++ for unsigned integer, as per-increment is cheaper(its about 5 gas per iteration cheaper)

i++ increments i and returns initial value of i. Which means

uint i =  1;
i++; // ==1 but i ==2

But ++i returns the actual incremented value:

uint i = 1;
++i; // ==2 and i ==2 , no need for temporary variable here

In the first case, the compiler has create a temporary variable (when used) for returning 1 instead of 2.

Instances:

Swivel/Swivel.sol:100: Swivel/Swivel.sol:269: Swivel/Swivel.sol:418: Swivel/Swivel.sol:511: Swivel/Swivel.sol:564:

Swivel/Swivel.sol:100:      unchecked {i++;}
Swivel/Swivel.sol:269:      unchecked {i++;}
Swivel/Swivel.sol:418:        i++;
Swivel/Swivel.sol:511:        x++;
Swivel/Swivel.sol:564:        i++;


robrobbins commented 2 years ago

items addressed elsewhere, i'll mark as resolved for the comment about custom errors which we did but not as part of a ticket - this mentions it tho.