Foundation Drop contest - 0xkatana's results

Foundation is a web3 destination.

General Information

Platform: Code4rena

Start Date: 11/08/2022

Pot Size: $40,000 USDC

Total HM: 8

Participants: 108

Period: 4 days

Judge: hickuphh3

Total Solo HM: 2

Id: 152

League: ETH

Foundation

Findings Distribution

Researcher Performance

Rank: 82/108

Findings: 1

Award: $40.70

๐ŸŒŸ Selected for report: 0

๐Ÿš€ Solo Findings: 0

[G-01] Redundant zero initialization

Solidity does not recognize null as a value, so uint variables are initialized to zero. Setting a uint variable to zero is redundant and can waste gas.

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/MarketFees.sol#L126 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/MarketFees.sol#L198 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/MarketFees.sol#L484 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L115 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L135 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L227 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L261 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L320 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/libraries/BytesLibrary.sol#L25 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/libraries/BytesLibrary.sol#L44

Remove the redundant zero initialization uint256 i; instead of uint256 i = 0;

[G-02] Split up require statements instead of &&

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

One example is

require( !callData.startsWith(type(IERC20Approve).interfaceId) && !callData.startsWith(type(IERC20IncreaseAllowance).interfaceId), "Split: ERC20 tokens must be split" );

This can be improved to

require(!callData.startsWith(type(IERC20Approve).interfaceId)); require(!callData.startsWith(type(IERC20IncreaseAllowance).interfaceId), "Split: ERC20 tokens must be split" );

One places had require statements with logical "and"s. Instead, split into two to save gas https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L192

Use separate require statements instead of concatenating with &&

[G-03] Cache array length before loop

Caching the array length outside a loop saves reading it on each iteration, as long as the array's length is not changed during the loop. This saves gas.

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L115 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L135 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L227 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L261 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L320

Cache the array length before the for loop

[G-04] Use != 0 instead of > 0

Using > 0 uses slightly more gas than using != 0. Use != 0 when comparing uint variables to zero, which cannot hold values below zero

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L88 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L130 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L131 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/MarketFees.sol#L244 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/OZERC165Checker.sol#L36

Replace > 0 with != 0 to save gas

[G-05] Short require strings save gas

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.

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L173 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L182 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L203 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L227 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L130 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L172 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L238 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L158 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L268 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L327 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/roles/MinterRole.sol#L22 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/roles/AdminRole.sol#L19 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/OZAccessControlUpgradeable.sol#L137 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/OZAccessControlUpgradeable.sol#L152 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/AdminRole.sol#L20 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L58 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L63 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L74 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L87 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L88 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L89

Shorten all require strings to less than 32 characters

[G-06] Use prefix not postfix in loops

Using a prefix increment (++i) instead of a postfix increment (i++) saves gas for each loop cycle and so can have a big gas impact when the loop executes on a large number of elements.

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L227 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L261

Use prefix not postfix to increment in a loop

[G-07] For loop incrementing can be unsafe

For loops that use i++ do not need to use safemath for this operation because the loop would run out of gas long before this point. Making this addition operation unsafe using unchecked saves gas.

Sample code to make the for loop increment unsafe

for (uint i = 0; i < length; i = unchecked_inc(i)) { // do something that doesn't change the value of i } function unchecked_inc(uint i) returns (uint) { unchecked { return i + 1; } }

Idea borrowed from https://gist.github.com/hrkrshnn/ee8fabd532058307229d65dcd5836ddc#the-increment-in-for-loop-post-condition-can-be-made-unchecked

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L227 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L261 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L591 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L718 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L760 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L780 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L807

Make the increment in for loops unsafe to save gas

[G-08] Use iszero assembly for zero checks

Comparing a value to zero can be done using the iszero EVM opcode. This can save gas

Source from t11s https://twitter.com/transmissions11/status/1474465495243898885

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L268 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L211 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L255 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L426 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L449 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L520 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L534 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L565 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L593 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L684 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L720 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L762 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L782 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L809 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/CollateralManagement.sol#L37 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/nftDropMarket/NFTDropMarketFixedPriceSale.sol#L127 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/nftDropMarket/NFTDropMarketFixedPriceSale.sol#L141 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/nftDropMarket/NFTDropMarketFixedPriceSale.sol#L176 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/nftDropMarket/NFTDropMarketFixedPriceSale.sol#L184 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L74 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L88 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/MarketFees.sol#L315 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/MarketFees.sol#L432 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/MarketFees.sol#L453 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/MarketFees.sol#L494 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/SendValueWithFallbackWithdraw.sol#L39 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L221 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/libraries/LockedBalance.sol#L36 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/libraries/LockedBalance.sol#L57 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/libraries/LockedBalance.sol#L78 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/libraries/LockedBalance.sol#L101 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/libraries/LockedBalance.sol#L105

Use the assembly iszero evm opcode to compare values to zero

[G-09] Add payable to functions that won't receive ETH

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

There are many functions that have the auth modifier in the contracts. Some examples are https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L202 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L226 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L159 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L195 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L209 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L220

Add payable to these functions for gas savings

[G-10] Add payable to constructors that won't receive ETH

Identifying a constructor as payable saves gas. Constructors should only be called by the admin or deployer and should not mistakenly receive ETH. Constructors can be payable to save gas.

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L181 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L101 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L95 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L196 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/ContractFactory.sol#L30 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/MarketFees.sol#L83 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/FETHNode.sol#L22 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/FoundationTreasuryNode.sol#L47 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropMarket.sol#L82

Add payable to these functions for gas savings

[G-11] Use internal function in place of modifier

An internal function can save gas vs. a modifier. A modifier inlines the code of the original function but an internal function does not.

Source https://blog.polymath.network/solidity-tips-and-tricks-to-save-gas-and-reduce-bytecode-size-c44580b218e6#dde7

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L172 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L87 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L92 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L183 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/roles/MinterRole.sol#L21 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/roles/AdminRole.sol#L18 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/AdminRole.sol#L19 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L57 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/ContractFactory.sol#L21 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/FoundationTreasuryNode.sol#L28 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/FoundationTreasuryNode.sol#L36 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L114

Use internal functions in place of modifiers to save gas.

[G-12] Use type(uint128).max

Using type(uint128).max uses less gas than other options for the constant value uint256 private constant last128BitsMask = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;. Source https://forum.openzeppelin.com/t/using-the-maximum-integer-in-solidity/3000/13

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/libraries/LockedBalance.sol#L24

Use type(uint128).max

[G-13] Use uint not bool

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.

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L266 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L291 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L234 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L382 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L397 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/roles/MinterRole.sol#L54 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/roles/AdminRole.sol#L47 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/OperatorRole.sol#L56 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/AdminRole.sol#L65 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/CollectionRoyalties.sol#L80 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/FETHNode.sol#L46

Replace bool variables with uints

[G-14] Use uint256 not smaller ints

From the solidity docs

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.

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L65 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L80 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L95 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L192 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L291 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L329 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L368 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L391 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L126 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L171 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L220 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L251 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L94 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L96 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L125 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L265 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L412 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L499 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L506 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L552 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L594 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L623

Replace smaller int or uint variables with uint256 variables

[G-15] Use newer solidity version

A solidity version before 0.8.X is used in this project. The latest release of solidity includes changes that can provide gas savings. The improvements include: The advantages of versions 0.8.* over <0.8.0 are:

Use solidity release 0.8.13 or above with Yul IR pipeline and other improvements for gas savings

[G-16] Use Solidity errors instead of require

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

Some solidity errors were used, but they did not fully replace the use of require. Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L173 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L182 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L203 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L227 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L262 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L88 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L93 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L130 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L131 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L172 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L179 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTDropCollection.sol#L238 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L158 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L263 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L264 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L268 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollection.sol#L327 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/roles/MinterRole.sol#L22 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/roles/AdminRole.sol#L19 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/OZAccessControlUpgradeable.sol#L37 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/OZAccessControlUpgradeable.sol#L137 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/OZAccessControlUpgradeable.sol#L152 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/AdminRole.sol#L20 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L58 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L63 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L74 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L87 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L88 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/collections/SequentialMintCollection.sol#L89 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/ContractFactory.sol#L22 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/ContractFactory.sol#L31 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L130 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L131 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L136 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L148 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L191 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L216

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

[G-17] Bitshift for divide by 2

When multiply or dividing by a power of two, it is cheaper to bitshift than to use standard math operations.

There is a divide by 2 operation on these lines https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L210 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/libraries/LockedBalance.sol#L100

Bitshift right by one bit instead of dividing by 2 to save gas

[G-18] Non-public variables save gas

Many constant variables are public, but changing the visibility of these variables to private or internal can save gas.

Locations where this was found include https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L125 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L130 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/FETH.sol#L135 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/roles/MinterRole.sol#L19 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/OZAccessControlUpgradeable.sol#L26 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/treasury/OZAccessControlUpgradeable.sol#L29 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/nftDropMarket/NFTDropMarketFixedPriceSale.sol#L70 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/NFTCollectionFactory.sol#L104 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/mixins/shared/ContractFactory.sol#L19

Declare some public variables as private or internal to save gas

[G-19] Use calldata instead of memory for function arguments

Using calldata instead of memory for function arguments saves gas sometimes. This can happen when a function is called externally and the memory array values are kept in calldata and copied to memory during ABI decoding (using the opcode calldataload and mstore). If the array is used in a for loop, arr[i] accesses the value in memory using a mload. If calldata is used instead, then instead of going via memory, the value is directly read from calldata using calldataload. That is, there are no intermediate memory operations that carries this value.

Many cases of function arguments using memory instead of calldata can use this improvement to save gas https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L129 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L167 https://github.com/code-423n4/2022-08-foundation/tree/main/contracts/PercentSplitETH.sol#L292

Source https://gist.github.com/hrkrshnn/ee8fabd532058307229d65dcd5836ddc#use-calldata-instead-of-memory-for-function-parameters

Change function arguments from memory to calldata

[G-20] Write contracts in vyper

The contracts are all written entirely in solidity. Writing contracts with vyper instead of solidity can save gas.

Source https://twitter.com/eiber_david/status/1515737811881807876 doggo demonstrates https://twitter.com/fubuloubu/status/1528179581974417414?t=-hcq_26JFDaHdAQZ-wYxCA&s=19

Write some or all of the contracts in vyper to save gas

#0 - HardlyDifficult

2022-08-19T00:07:18Z

Don't initialize variables with default values.

Invalid. This optimization technique is no longer applicable with the current version of Solidity.

[G-02] Split up require statements instead

This may save some gas, but for readability I prefer the current form.

Cache Array Length Outside of Loop

May be theoretically valid, but won't fix. I tested this: gas-reporter and our gas-stories suite is reporting a small regression using this technique. It also hurts readability a bit so we wouldn't want to include it unless it was a clear win.

Use != 0 instead of > 0

Invalid. We tested the recommendation and got the following results:

createNFTDropCollection gas reporter results: using > 0 (current): - 319246 ยท 319578 ยท 319361 using != 0 (recommendation): - 319252 ยท 319584 ยท 319367 impact: +6 gas

Use short error messages

Agree but won't fix. We use up to 64 bytes, aiming to respect the incremental cost but 32 bytes is a bit too short to provide descriptive error messages for our users.

++i costs less than i++

Agree and will fix.

[G-07] For loop incrementing can be unsafe

Invalid -- all examples provided are already unchecked.

Use assembly to check for zero address.

Won't fix. While this may save a tiny bit of gas, we reserve the use of assembly to areas where it would provide significant benefit or accomplish something that's otherwise not possible with Solidity alone.

Functions guaranteed to revert when called by normal users can be marked payable

Disagree. This could save gas but 1) this seems like a poor practice to encourage and could be error prone. and 2) we don't care about optimizing admin-only actions.

[G-11] Use internal function in place of modifier

Disagree, this can increase user costs which is more important than deployment costs.

[G-12] Use type(uint128).max

This may save a bit on deployment, but for consistency and readability in that context I prefer the current form.

[G-13] Use uint not bool

Agree and we are considering a change.

uints/ints smaller than 32 bytes (256 bits) incurs overhead.

Potentially valid but won't fix. This is uint32 to allow packing storage for a significant gas savings. Accepting the input as uint256 would incur additional overhead in checking for overflow before saving these values. Other inputs are logically limited to the size exposed, huge values cannot be used. Accepting the input as uint256 would incur additional overhead in checking for overflow before using these values.

[G-15] Use newer solidity version

Invalid, we are compiling with the latest version 0.8.16 per the hardhat.config.

Custom errors

Agree but won't fix at this time. We use these in the market but not in collections. Unfortunately custom errors are still not as good of an experience for users (e.g. on etherscan). We used them in the market originally because we were nearing the max contract size limit and this was a good way to reduce the bytecode. We'll consider this in the future as tooling continues to improve.

[G-17] Bitshift for divide by 2

The first example is not a / 2 -- invalid. The second was out of scope for this contest, but we'll consider a change there.

Using private rather than public for constants to saves gas.

Agree but won't fix. For ease of use and consistency we will continue to expose some constants publicly.

calldata

Valid and will fix, but the examples listed were out of scope for this contest.

[G-20] Write contracts in vyper

lol thanks

#1 - HickupHH3

2022-09-05T06:27:22Z

[G-20] Write contracts in vyper

lolol

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