Foundation Drop contest - brgltd'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: 39/108

Findings: 3

Award: $74.97

🌟 Selected for report: 0

🚀 Solo Findings: 0

[L-01] Use _safeMint() instead of mint()

OpenZeppelin recommendation is to use _safeMint() instead of mint() for ERC721Upgradeable.

_safeMint() will ensure that the recipient implements IERC721Receiver or is an EOA.

File: contracts/NFTDropCollection.sol 182: _mint(to, i);

https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTDropCollection.sol

[L-02] Missing constructor and initializer modifier for contracts using Initializable

Impact

OpenZeppelin recommends adding an empty constructor with the initializer modifier in order to avoid potential griefs, social engineering and other exploits.

File: contracts/NFTDropCollection.sol 62: contract NFTCollectionFactory is ICollectionFactory, Initializable, Gap10000 {

https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTCollectionFactory.sol

File: contracts/NFTDropCollection.sol 28: contract NFTDropCollection is

https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTDropCollection.sol

File: contracts/NFTDropMarket.sol 63: contract NFTDropMarket is

https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTDropMarket.sol

File: contracts/mixins/collections/SequentialMintCollection.sol 13: abstract contract SequentialMintCollection is ITokenCreator, Initializable, ERC721BurnableUpgradeable {

https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/collections/SequentialMintCollection.sol

File: contracts/mixins/roles/AdminRole.sol 12: abstract contract AdminRole is Initializable, AccessControlUpgradeable {

https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/roles/AdminRole.sol

File: contracts/mixins/treasury/AdminRole.sol 13: abstract contract AdminRole is Initializable, OZAccessControlUpgradeable {

https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/treasury/AdminRole.sol

File: contracts/mixins/roles/MinterRole.sol 14: abstract contract MinterRole is Initializable, AccessControlUpgradeable, AdminRole {

https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/roles/MinterRole.sol

Ensure that the modifier is applied to the implementation contract. If the default constructor is currently being used, it should be changed to be an explicit one with the modifier applied.

[NC-01] Lock the pragma version

Even if the idea is to make use of the latests versions of solidity, I would still recommend to lock the pragma for contracts that will be deployed to the mainnet and are not intended to be consumed by other developers.

All the 20 contracts in scope are rounding the pragma version.

https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTCollectionFactory.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTDropCollection.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTDropMarket.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/libraries/AddressLibrary.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/libraries/ArrayLibrary.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/libraries/BytesLibrary.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/collections/CollectionRoyalties.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/collections/SequentialMintCollection.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/nftDropMarket/NFTDropMarketCore.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/nftDropMarket/NFTDropMarketFixedPriceSale.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/roles/AdminRole.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/roles/MinterRole.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/Constants.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/ContractFactory.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/FETHNode.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/FoundationTreasuryNode.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/Gap10000.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/shared/MarketSharedCore.sol https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/mixins/treasury/AdminRole.sol

[NC-02] Replace public with external for functions not called by the contract internally

File: contracts/NFTDropCollection.sol 159: function burn(uint256 tokenId) public override onlyAdmin {

https://github.com/code-423n4/2022-08-foundation/blob/main/contracts/NFTDropCollection.sol

File: contracts/mixins/shared/FoundationTreasuryNode.sol 59: function getFoundationTreasury() public view returns (address payable treasuryAddress) {

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

#0 - HardlyDifficult

2022-08-18T16:10:00Z

Use safeMint

Agree will fix - for context see our response here.

Use constructor to initialize templates

Agree this is a good best practice to add. Will fix.

Use fixed pragma

Disagree. We intentionally use a floating pragma in order to make integrating with contracts easier. Other contract developers are looking to interact with our contracts and they may be on a different version than we use. The pragma selected for our contracts is the minimum required in order to correctly compile and function. This way integration is easier if they lag a few versions behind, or if they use the latest but we don't bump our packages frequently enough, and when we do upgrade versions unless there was a breaking solidity change -- it should just swap in by incrementing our npm package version.

[NC-02] Replace public with external

Invalid. burn is an override so it must remain public. getFoundationTreasury is used internally by MarketFees.

Use custom error instead of require() strings

Replacing require() strings with custom error would yield the following improvements on gas deployments (diff formatted for readability).

$ git diff --no-index gas-stories-original.txt gas-stories-with-custom-errors.txt diff --git a/gas-stories-original.txt b/gas-stories-with-custom-errors.txt index e2b107d..73442b8 100644 --- a/gas-stories-original.txt +++ b/gas-stories-with-custom-errors.txt @@ -1,6 +1,6 @@ Deployments - Avg -NFTCollection 2899976 -NFTDropCollection 3409650 + Avg +NFTCollection 2704389 +NFTDropCollection 3056772

There are 12 instances of this issue

File: contracts/NFTCollection.sol 158: require(tokenCreatorPaymentAddress != address(0), "NFTCollection: tokenCreatorPaymentAddress is required"); 263: require(bytes(tokenCID).length != 0, "NFTCollection: tokenCID is required"); 264: require(!cidToMinted[tokenCID], "NFTCollection: NFT was already minted"); 268: require(maxTokenId == 0 || tokenId <= maxTokenId, "NFTCollection: Max token count has already been minted"); 327: require(_exists(tokenId), "NFTCollection: URI query for nonexistent token");
File: contracts/NFTDropCollection.sol 88: require(bytes(_baseURI).length > 0, "NFTDropCollection: `_baseURI` must be set"); 93: require(postRevealBaseURIHash != bytes32(0), "NFTDropCollection: Already revealed"); 130: require(bytes(_symbol).length > 0, "NFTDropCollection: `_symbol` must be set"); 131: require(_maxTokenId > 0, "NFTDropCollection: `_maxTokenId` must be set"); 172: require(count != 0, "NFTDropCollection: `count` must be greater than 0"); 179: require(latestTokenId <= maxTokenId, "NFTDropCollection: Exceeds max tokenId"); 238: require(_postRevealBaseURIHash != bytes32(0), "NFTDropCollection: use `reveal` instead");

#0 - HardlyDifficult

2022-08-19T15:32:38Z

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.

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