Strict inequalities (>) are more expensive than non-strict ones (>=)
2
G-2
x += y costs more gas than x = x + y for state variables
7
G-3
Use calldata instead of memory in external functions
3
G-4
Using bools for storage incurs overhead
3
G-5
Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead
7
G-6
Use assembly to check for address(0)
11
Total instances found in this contest: 33 | Among all files in scope
G-01 Strict inequalities (>) are more expensive than non-strict ones (>=)
Strict inequalities (>) are more expensive than non-strict ones (>=). This is due to some supplementary checks (ISZERO, 3 gas. I suggest using >= instead of > to avoid some opcodes here:
// 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.
Refer Here 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
G-05 Usage of uints/ints 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.
Gas Optimization
Total instances found in this contest: 33 | Among all files in scope
G-01 Strict inequalities (>) are more expensive than non-strict ones (>=)
Strict inequalities (>) are more expensive than non-strict ones (>=). This is due to some supplementary checks (ISZERO, 3 gas. I suggest using >= instead of > to avoid some opcodes here:
Instances:
contracts/JBTiered721Delegate.sol:551: _data.metadata.length > 36 && contracts/JBTiered721DelegateStore.sol:965: _storedTier.contributionFloor > _bestContributionFloor &&
References:
https://code4rena.com/reports/2022-04-badger-citadel/#g-31--is-cheaper-than
G-02 x += y costs more gas than x = x + y for state variables
Instances:
contracts/JBTiered721DelegateStore.sol:354: supply += _storedTier.initialQuantity - _storedTier.remainingQuantity; contracts/JBTiered721DelegateStore.sol:409: units += _balance * _storedTierOf[_nft][_i].votingUnits; contracts/JBTiered721DelegateStore.sol:506: balance += tierBalanceOf[_nft][_owner][_i]; contracts/JBTiered721DelegateStore.sol:534: weight += _storedTierOf[_nft][tierIdOfToken(_tokenIds[_i])].contributionFloor; contracts/JBTiered721DelegateStore.sol:563: weight += contracts/JBTiered721DelegateStore.sol:827: numberOfReservesMintedFor[msg.sender][_tierId] += _count; contracts/libraries/JBIpfsDecoder.sol:52: carry += uint256(digits[j]) * 256;
References:
https://github.com/code-423n4/2022-05-backd-findings/issues/108
G-03 Use calldata instead of memory in external functions
Use calldata instead of memory in external functions to save gas.
Instances:
contracts/JBTiered721Delegate.sol:386: function setBaseUri(string memory _baseUri) external override onlyOwner { contracts/JBTiered721DelegateStore.sol:1016: ) external override returns (uint256[] memory tokenIds, uint256 leftoverAmount) { contracts/JBTiered721DelegateStore.sol:1091: function recordBurn(uint256[] memory _tokenIds) external override {
Reference:
https://code4rena.com/reports/2022-04-badger-citadel/#g-12-stakedcitadeldepositall-use-calldata-instead-of-memory
G-04 Using bools for storage incurs overhead
Refer Here 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
Instances:
contracts/JBTiered721Delegate.sol:543: bool _expectMintFromExtraFunds; contracts/JBTiered721Delegate.sol:546: bool _dontOverspend; contracts/JBTiered721Delegate.sol:555: bool _dontMint;
References:
https://code4rena.com/reports/2022-06-notional-coop#8-using-bools-for-storage-incurs-overhead
G-05 Usage of uints/ints 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.
https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Use a larger size then downcast where needed
Instances:
contracts/JBTiered721DelegateStore.sol:689: contributionFloor: uint80(_tierToAdd.contributionFloor), contracts/JBTiered721DelegateStore.sol:690: lockedUntil: uint48(_tierToAdd.lockedUntil), contracts/JBTiered721DelegateStore.sol:691: remainingQuantity: uint40(_tierToAdd.initialQuantity), contracts/JBTiered721DelegateStore.sol:692: initialQuantity: uint40(_tierToAdd.initialQuantity), contracts/JBTiered721DelegateStore.sol:693: votingUnits: uint16(_tierToAdd.votingUnits), contracts/JBTiered721DelegateStore.sol:694: reservedRate: uint16(_tierToAdd.reservedRate), contracts/libraries/JBIpfsDecoder.sol:48: uint8 digitlength = 1;
G-06 Use assembly to check for address(0)
Saves 6 gas per instance if using assembly to check for address(0)
e.g.
Instances
contracts/JBTiered721Delegate.sol:105: if (_storedFirstOwner != address(0)) return _storedFirstOwner; contracts/JBTiered721Delegate.sol:146: if (address(_resolver) != address(0)) return _resolver.getUri(_tokenId); contracts/JBTiered721Delegate.sol:729: if (_from != address(0)) { contracts/JBTiered721Delegate.sol:736: _to != address(0) && contracts/JBTiered721DelegateStore.sol:609: if (_storedReservedTokenBeneficiaryOfTier != address(0)) contracts/JBTiered721DelegateStore.sol:700: _tierToAdd.reservedTokenBeneficiary != address(0) && contracts/JBTiered721DelegateStore.sol:872: if (_from != address(0)) contracts/JBTiered721DelegateStore.sol:877: if (_to != address(0)) { contracts/JB721TieredGovernance.sol:282: if (_from != address(0)) { contracts/JB721TieredGovernance.sol:291: if (_to != address(0)) { contracts/JBTiered721DelegateDeployer.sol:99: if (_deployTiered721DelegateData.owner != address(0))