code-423n4 / 2022-03-volt-findings

0 stars 0 forks source link

Gas Optimizations #102

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

1. Use calldata instead of memory for function parameters

Impact

Use calldata instead of memory for function parameters. Having function arguments use calldata instead of memory can save gas.

Proof of Concept

At least two cases exist of function arguments using memory instead of calldata https://github.com/code-423n4/2022-03-volt/blob/main/contracts/refs/OracleRef.sol#L84 https://github.com/code-423n4/2022-03-volt/blob/main/contracts/peg/NonCustodialPSM.sol#L456

Tools Used

Manual analysis

Recommended Mitigation Steps

Change function arguments from memory to calldata

2. Add payable to functions that won't receive ETH

Impact

Marking a function as payable saves gas. Functions that have the onlyOwner modifier cannot be called by normal users and will not mistakenly receive ETH. These functions can be payable to save gas.

Proof of Concept

One function was found with the onlyOwner modifier that can be payable https://github.com/code-423n4/2022-03-volt/blob/main/contracts/oracle/OraclePassThrough.sol#L53

But all functions in Permissions.sol that have the onlyGovernor modifier or the onlyGuardian modifier can receive the same gas optimization

Tools Used

Manual analysis

Recommended Mitigation Steps

Add payable to functions with access control for gas savings

3. Split up require statements instead of &&

Impact

Combining require statement conditions with && logic uses unnecessary gas. It is better to split up each part of the logical statement into a separate require statements

Proof of Concept

One instance of this issue was found https://github.com/code-423n4/2022-03-volt/blob/main/contracts/volt/Volt.sol#L91

Tools Used

Manual analysis

Recommended Mitigation Steps

Use separate require statements instead of concatenating with && to save gas

4. Short require strings save gas

Impact

Strings in solidity are handled in 32 byte chunks. A require string longer than 32 bytes uses more gas. Shortening these strings will save gas.

Proof of Concept

Several cases of this gas optimization were found. These are a few examples, but more may exist

  1. https://github.com/code-423n4/2022-03-volt/blob/main/contracts/pcv/compound/ERC20CompoundPCVDeposit.sol#L36
  2. https://github.com/code-423n4/2022-03-volt/blob/main/contracts/utils/RateLimited.sol#L48
  3. https://github.com/code-423n4/2022-03-volt/blob/main/contracts/refs/CoreRef.sol#L48
  4. https://github.com/code-423n4/2022-03-volt/blob/main/contracts/refs/CoreRef.sol#L56
  5. https://github.com/code-423n4/2022-03-volt/blob/main/contracts/refs/CoreRef.sol#L72
  6. https://github.com/code-423n4/2022-03-volt/blob/main/contracts/refs/CoreRef.sol#L82

Tools Used

Manual analysis

Recommended Mitigation Steps

Shorten require strings

5. Use Solidity errors instead of require

Impact

Solidity errors introduced in version 0.8.4 can save gas on revert conditions https://blog.soliditylang.org/2021/04/21/custom-errors/ https://twitter.com/PatrickAlphaC/status/1505197417884528640

Proof of Concept

Error messages are not used in the contract, so all require blocks could receive a gas optimization

Tools Used

Manual analysis

Recommended Mitigation Steps

Replace require blocks with new solidity errors from solidity 0.8.4 described in https://blog.soliditylang.org/2021/04/21/custom-errors/

ElliotFriedman commented 2 years ago
  1. Add payable to functions that won't receive ETH, this was invalid and not allowed as a gas optimization per contract rules