sablier-labs / v1-protocol

Core smart contracts of the Sablier V1 protocol
https://sablier.finance
GNU General Public License v3.0
263 stars 79 forks source link

Gas Optimizations #31

Closed kadenzipfel closed 1 year ago

kadenzipfel commented 4 years ago

I've gone through the various Sablier contracts in search of possible gas optimizations. The following are possible improvements that can be made to the contracts to save gas.

Disclaimer: I'm by no means an expert on gas optimization, and some or all of my suggestions could be wrong. I just thought it would be fun to contribute to a project that I enjoy using.

createSalary() - Payroll.sol line 252-273

A temporary variable salaryId is created to represent the global variable nextSalaryId. Instead of loading nextSalaryId from storage on lines 265 and 269, we can simply use the temporary variable salaryId.

hundredPercent & onePercent - Sablier.sol lines 25 & 30

Although it may be useful to represent these values as constant global variables, it's quite expensive to pull them out of storage each time they're used. In place of these variables, you will save gas by just referencing the values.

takeEarnings() - Sablier.sol line 172-187

earnings[tokenAddress] is used three times throughout this function. You can save gas by using a temporary variable. This may also be applicable to withdrawFromCompoundingStreamInternal() as well as cancelCompoundingStreamInternal().

interestOf() - Sablier.sol line 351-432

Global variable fee is used three times. Can be represented with a temporary variable.

createStream() - Sablier.sol line 473-521

Temporary variable streamId is used to represent global variable nextStreamId, yet the global variable continues to be used when the temporary variable will suffice.

getStream() - Sablier.sol line 197-220

A temporary variable can represent streams[streamId]. Same can be done for getCompoundingStream() with both streams[streamId] and compoundingStreamVars[streamId].

withdrawFromStreamInternal() - Sablier.sol line 664-678

Temporary variable stream is created to represent streams[streamId], which can be used throughout the function. Same thing for withdrawFromCompoundingStreamInternal(), cancelStreamInternal() and cancelCompoundingStreamInternal().

Constant variables - Exponential.sol lines 13-15

It's costly and unnecessary (as far as I can tell) to assign these values to global variables.

If wanted, I will gladly make a pull request to make all these changes, just let me know.

PaulRBerg commented 1 year ago

Hi @kadenzipfel, I am sorry for never responding to this issue. I have just seen it now!

Unfortunately, because we want the code in this repository to match the deployed bytecode exactly, we will choose not to implement these optimizations. We're also getting ready to ship Sablier V2, so V1 will get deprecated soon.