nibblVaultFactory.sol is already importing everything from
NibblVault.sol which has Ierc20.sol ,Ierc1155.sol,IERC721.sol already imported from it .
Remove Ierc20.sol and Ierc1155.sol ,IERC721.sol from nibblVaultFactory.sol.
instances include:
nibblVaultFactory.sol :4,5,6
2. Use 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) Source Custom Errors in Solidity: 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 include:
nibblVaultFactory.sol: 48,49,107,131,141,149,166
nibblVault.sol:139,129,146,147,154,184,185,
Reduce the size of error messages (Long revert Strings)
Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition is met. Revert strings that are longer than 32 bytes require at least one additional mstore, along with additional overhead for computing memory offset, etc.
1 byte for character
Make functions with governance modifier payable saves gas because payable function dont have to check msg.value ==0 and since it doesn't affect the function because governance is only people to call the function it saves gas.
nibblVaultFactory.sol: 99,123,140,158,173,179
Basket.sol: almost the whole contract is approve by owner
AccessControlMechanism.sol:32,40,47
use mutiple require statements instead of && to save gas
because variables uninitlized in evm is still 0 and saves 3 gas
nibblVault.sol:506,525,547
Basket.sol::43,70,93
++i costs less gas compared to i++ or i += 1
++i costs less gas compared to i++ or i += 1 for unsigned integer, as pre-increment is cheaper (about 5 gas per iteration). This statement is true even with the optimizer enabled. i++ increments i and returns the 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 too, so no need for a temporary variable In the first case, the compiler has to create a temporary variable (when used) for returning 1 instead of 2
instances include:
nibblVault.sol:506,525,547,561
Basket.sol::43,70,93
make array.length cached to a variable
nibblVault.sol:506,525,547
Basket.sol::43,70,93
Unchecking arithmetics operations that can’t underflow/overflow
Solidity version 0.8+ comes with implicit overflow and underflow checks on unsigned integers. When an overflow or an underflow isn’t possible (as an example, when a comparison is made before the arithmetic operation), some gas can be saved by using an unchecked block: Checked or Unchecked Arithmetic. I suggest wrapping with an unchecked block:
Same thing with second unchecked because total can't overflow amount cant overflow
nibblVault.sol:506,525,547
Basket.sol::43,70,93
you can make unlucked uninlized in the beigning because your initlizing it in the constructor to save gas
nibblVault.sol:126
do keccak256 function of change not just assign the variable on chain to save gas
waste of gas in struct becaue uint256 takes of more gas then a uint32 because of how the evm works, the evm has to bit wise converion on uint 256 to turn into a uint32
// 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.
AccessControlMechanism.sol:16
dont use abi.encode instead use abi.encodepacked to save gas
1. unused import statments can also save gas
nibblVaultFactory.sol
is already importing everything fromNibblVault.sol
which hasIerc20.sol
,Ierc1155.sol
,IERC721.sol
already imported from it . RemoveIerc20.sol
andIerc1155.sol
,IERC721.sol
fromnibblVaultFactory.sol
. instances include:nibblVaultFactory.sol
:4,5,62. Use 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) Source Custom Errors in Solidity: 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 include:
nibblVaultFactory.sol
: 48,49,107,131,141,149,166nibblVault.sol
:139,129,146,147,154,184,185,Reduce the size of error messages (Long revert Strings)
Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition is met. Revert strings that are longer than 32 bytes require at least one additional mstore, along with additional overhead for computing memory offset, etc. 1 byte for character
nibblVaultFactory.sol
: 48,49,107,131,141,149,166,325,351,387,399,400,404,444,475,486,496,505,516,524,536,546,561,570,make onlyadmin function payable to save gas
Make functions with governance modifier payable saves gas because payable function dont have to check
msg.value ==0
and since it doesn't affect the function because governance is only people to call the function it saves gas.nibblVaultFactory.sol
: 99,123,140,158,173,179Basket.sol
: almost the whole contract is approve by ownerAccessControlMechanism.sol
:32,40,47use mutiple require statements instead of && to save gas
nibblVaultFactory.sol
:107,131,149,166Basket.sol
:36,42,53,62,69,79,86,93make variables uninitlized to save gas
because variables uninitlized in evm is still 0 and saves 3 gas
nibblVault.sol
:506,525,547Basket.sol
::43,70,93++i costs less gas compared to i++ or i += 1
++i costs less gas compared to i++ or i += 1 for unsigned integer, as pre-increment is cheaper (about 5 gas per iteration). This statement is true even with the optimizer enabled. i++ increments i and returns the 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 too, so no need for a temporary variable In the first case, the compiler has to create a temporary variable (when used) for returning 1 instead of 2 instances include:
nibblVault.sol
:506,525,547,561Basket.sol
::43,70,93make array.length cached to a variable
nibblVault.sol
:506,525,547Basket.sol
::43,70,93Unchecking arithmetics operations that can’t underflow/overflow
Solidity version 0.8+ comes with implicit overflow and underflow checks on unsigned integers. When an overflow or an underflow isn’t possible (as an example, when a comparison is made before the arithmetic operation), some gas can be saved by using an unchecked block: Checked or Unchecked Arithmetic. I suggest wrapping with an unchecked block: Same thing with second unchecked because total can't overflow amount cant overflow
nibblVault.sol
:506,525,547Basket.sol
::43,70,93you can make unlucked uninlized in the beigning because your initlizing it in the constructor to save gas
nibblVault.sol
:126do keccak256 function of change not just assign the variable on chain to save gas
nibblVault.sol
:51AccessControlMechanism.sol
:12,13,14you can constant variables immutable to save gas in certin cases like with getting keccak hash assign on constant
nibblVault.sol
:51AccessControlMechanism.sol
:12,13,14waste of gas in struct becaue uint256 takes of more gas then a uint32 because of how the evm works, the evm has to bit wise converion on uint 256 to turn into a uint32
Twav.sol:6
Using bools 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.
AccessControlMechanism.sol
:16dont use abi.encode instead use abi.encodepacked to save gas
abi.encodepacked dosnt pad zeros EIP721Base.sol#L16