Foundation Drop contest - ignacio'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: 84/108

Findings: 2

Award: $33.77

馃専 Selected for report: 0

馃殌 Solo Findings: 0

Findings Information

Labels

bug
duplicate
2 (Med Risk)

Awards

13.1705 USDC - $13.17

External Links

1 _SAFEMINT() SHOULD BE USED RATHER THAN _MINT() WHEREVER POSSIBLE

_mint() is discouraged in favor of _safeMint() which ensures that the recipient is either an EOA or implements IERC721Receiver https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTCollection.sol#L130 https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTCollection.sol#L143 https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTCollection.sol#L159 https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTCollection.sol#L271

2 ABI.ENCODEPACKED() SHOULD NOT BE USED WITH DYNAMIC TYPES WHEN PASSING THE RESULT TO A HASH FUNCTION SUCH AS KECCAK256()

Use abi.encode() instead which will pad items to 32 bytes, which will prevent hash collisions https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTCollectionFactory.sol#L449

#0 - HardlyDifficult

2022-08-18T21:30:59Z

Use safeMint

Agree will fix - for context see our response here.

abi.encodePacked() should not be used

It's a gas savings to use encodePacked for the use cases we support here. There does not appear to be a compelling reason to change.

#1 - HickupHH3

2022-08-31T11:06:24Z

dup of #183

1)<ARRAY>.LENGTH SHOULD NOT BE LOOKED UP IN EVERY LOOP OF A FOR-LOOP and Increments can be unchecked

The overheads outlined below are PER LOOP, excluding the first loop storage arrays incur a Gwarmaccess (100 gas) memory arrays use MLOAD (3 gas) calldata arrays use CALLDATALOAD (3 gas) Caching the length changes each of these to a DUP<N> (3 gas), and gets rid of the extra DUP<N> needed to store the stack offset ( ++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- AND WHILE-LOOPS ++I COSTS LESS GAS THAN I++ https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/MarketFees.sol#L126 https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/MarketFees.sol#L198 https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/MarketFees.sol#L484 https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/MarketFees.sol#L503

2 <X> += <Y> COSTS MORE GAS THAN <X> = <X> + <Y> FOR STATE VARIABLES

https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/MarketFees.sol#L134

#3 Check msg.value first - 1 gas per instance - 3 gas total Reading msg.value costs 2 gas, while reading from memory costs 3, this will save 1 gas with no downside https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/FETHNode.sol#L56

4 Use != 0 instead of > 0 at the above mentioned codes. The variable is uint, so it will not be below 0 so it can just check != 0.

!= 0 costs less gas compared to > 0 for unsigned integers in require statements with the optimizer enabled https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/MarketFees.sol#L244

5 USING CALLDATA INSTEAD OF MEMORY FOR READ-ONLY ARGUMENTS IN EXTERNAL FUNCTIONS SAVES GAS

When a function with a memory array is called externally, the abi.decode() step has to use a for-loop to copy each index of the calldata to the memory index. Each iteration of this for-loop costs at least 60 gas (i.e. 60 * <mem_array>.length). Using calldata directly, obliviates the need for such a loop in the contract code and runtime execution. If the array is passed to an internal function which passes the array to another internal function where the array is modified and therefore memory is used in the external call, it鈥檚 still more gass-efficient to use calldata when the external function uses modifiers, since the modifiers may prevent the internal functions from being called. Structs have the same overhead as an array of length one https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTCollectionFactory.sol#L371 https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTCollection.sol#L105 https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTCollection.sol#L282

#0 - HardlyDifficult

2022-08-17T09:03:25Z

1).LENGTH SHOULD NOT BE LOOKED UP IN EVERY LOOP OF A FOR-LOOP and Increments can be unchecked

4 instances were linked and 3 of those are already unchecked -- so those are invalid. The other is a read only function not intended to be used on-chain, but as a best practice we will add unchecked there as well.

2 += COSTS MORE GAS THAN = + FOR STATE VARIABLES

No impact. We made the recommended change and ran gas-reporter for our entire test suite. 0 impact detected. Even if there were a small benefit, we feel this hurts readability and would not be worth trivial savings.

3 Check msg.value first - 1 gas per instance - 3 gas total

Invalid. For the market in scope for this contest, shouldRefundSurplus is always false -- so the recommendation would prevent fail fast and cause gas to regress:

Running test/NFTDropMarket/fixedPrice/* Before: - 112650 路 663751 路 278013 After: - 112655 路 663756 路 278016 Impact: +5 gas

4 Use != 0 instead of > 0 at the above mentioned codes. The variable is uint, so it will not be below 0 so it can just check != 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

5 USING CALLDATA INSTEAD OF MEMORY FOR READ-ONLY ARGUMENTS IN EXTERNAL FUNCTIONS SAVES GAS

3 examples were included:

  • createNFTDropCollectionWithPaymentFactory and initialize valid & will fix. This saves ~50 gas on createNFTCollection and ~60 gas on createNFTDropCollectionWithPaymentFactory
  • baseURI invalid, the memory reference here is a return param - calldata cannot be used.
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