Drips Protocol contest - ReyAdmirado's results

An Ethereum protocol for streaming and splitting funds.

General Information

Platform: Code4rena

Start Date: 25/01/2023

Pot Size: $90,500 USDC

Total HM: 3

Participants: 26

Period: 9 days

Judge: GalloDaSballo

Id: 209

League: ETH

Drips Protocol

Findings Distribution

Researcher Performance

Rank: 16/26

Findings: 1

Award: $131.98

Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Labels

bug
G (Gas Optimization)
grade-b
G-08

Awards

131.9758 USDC - $131.98

External Links

1. state variables should be cached in stack variables rather than re-reading them from storage (ones not caught by c4udit)

The instances below point to the second+ access of a state variable within a function. Caching of a state variable replace each Gwarmaccess (100 gas) with a much cheaper stack read. Other less obvious fixes/optimizations include having local memory caches of state variable structs, or having local caches of state variable contracts/addresses.

state.updateTime can be cached because the require check will usually be true so we save 100 gas by risking 3 more gas use.

2. <x> += <y> costs more gas than <x> = <x> + <y> for state variables

Using the addition operator instead of plus-equals saves gas

3. not using the named return variables when a function returns, wastes deployment gas

4. can make the variable outside the loop to save gas

make the variable outside and only give the value to variable inside

5. ++i/i++ should be unchecked{++i}/unchecked{i++} when it is not possible for them to overflow, as is the case when used in for-loop and while-loops

The unchecked keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas PER LOOP

6. using bool for storage incurs overhead

Booleans are more expensive than uint256 or any type that takes up a full word because each write operation emits an extra SLOAD to first read the slot's contents, replace the bits taken up by the boolean, and then write back. This is the compiler's defense against contract upgrades and pointer aliasing, and it cannot be disabled. Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas) for the extra SLOAD, and to avoid Gsset (20000 gas) when changing from ‘false’ to ‘true’, after having been ‘true’ in the past

7. internal functions only called once can be inlined to save gas

Not inlining costs 20 to 40 gas because of two extra JUMP instructions and additional stack operations needed for function calls.

these functions can be inlined inside DripsHub.sol because its only used once there _receiveDrips

8. usage of uint/int smaller than 32 bytes (256 bits) incurs overhead

When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size. Each operation involving a uint8 costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8) as compared to ones involving uint256, due to the compiler having to clear the higher bits of the memory word before operating on the uint8, as well as the associated stack operations of doing so. Use a larger size then downcast where needed https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Use a larger size then downcast where needed

_AMT_PER_SEC_EXTRA_DECIMALS

_cycleSecs (also casting is done to change it to 256 bits in some places which costs extra gas)

9. Ternary over if ... else

Using ternary operator instead of the if else statement saves gas.

10. public functions not called by the contract should be declared external instead

Contracts are allowed to override their parents’ functions and change the visibility from external to public and can save gas by doing so.

registerDriver

mint

changeAdmin

authorize

11. before some functions we should check some variables for possible gas save

before transfer we should check for amount being 0 with a require of if check so the function doesnt run when its not gonna do anything

12. instead of calculating a statevar with keccak256() every time the contract is made, pre calculate them before and only give the result to it

keccak256(bytes(CALL_SIGNED_TYPE_NAME)) always has the same answer, so it can be pre calculated

_erc1967Slot() function will basically do some operation on a string, all the operations can be pre calculated in these places to save gas

13. Non-strict inequalities are cheaper than strict ones

In the EVM, there is no opcode for non-strict inequalities (>=, <=) and two operations are performed (> + = or < + =). consider replacing >= with the strict counterpart > and add - 1 to the second side

14. Setting the constructor to payable

You can cut out 10 opcodes in the creation-time EVM bytecode if you declare a constructor payable. Making the constructor payable eliminates the need for an initial check of msg.value == 0 and saves 13 gas on deployment with no security risks.

15. instead of assigning to zero use delete

assigning to zero uses more gas than using delete , and they both assign variables to default value. so it is encouraged if the data is no longer needed use delete instead.

16. Optimize names to save gas

Contracts most called functions could simply save gas by function ordering via Method ID. Calling a function at runtime will be cheaper if the function is positioned earlier in the order (has a relatively lower Method ID) because 22 gas is added to the cost of a function for every position that came before it. The caller can save on gas if you prioritize most called functions.

See more here. you can use this tool to get the optimized version for function and properties signatures

  • DripsHub.sol has 33 public functions that are gonna be used externally used, ordering them for Method ID will be a huge gas save

  • NFTDriver.sol has 16 public functions that are gonna be used externally used, ordering them for Method ID will be a huge gas save

  • Managed.sol has 9 public functions that are gonna be used externally used, ordering them for Method ID will be a nice gas save

#0 - GalloDaSballo

2023-02-24T11:00:38Z

100 SLOAD

500 from +=

300 from unchecked

900

#1 - c4-judge

2023-02-24T11:02:05Z

GalloDaSballo marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter