NextGen - 0xSolus's results

Advanced smart contracts for launching generative art projects on Ethereum.

General Information

Platform: Code4rena

Start Date: 30/10/2023

Pot Size: $49,250 USDC

Total HM: 14

Participants: 243

Period: 14 days

Judge: 0xsomeone

Id: 302

League: ETH

NextGen

Findings Distribution

Researcher Performance

Rank: 111/243

Findings: 1

Award: $13.98

Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Awards

13.9832 USDC - $13.98

Labels

bug
G (Gas Optimization)
grade-b
sufficient quality report
G-05

External Links

GAS

Cache variables to save gas.

  1. In NextGenCore.sol::createCollection() cache newCollectionIndex to save gas.
function createCollection(string memory _collectionName, string memory _collectionArtist, string memory _collectionDescription, string memory _collectionWebsite, string memory _collectionLicense, string memory _collectionBaseURI, string memory _collectionLibrary, string[] memory _collectionScript) external FunctionAdminRequired(this.createCollection.selector) { uint256 index = newCollectionIndex; collectionInfo[index].collectionName = _collectionName; collectionInfo[index].collectionArtist = _collectionArtist; collectionInfo[index].collectionDescription = _collectionDescription; collectionInfo[index].collectionWebsite = _collectionWebsite; collectionInfo[index].collectionLicense = _collectionLicense; collectionInfo[index].collectionBaseURI = _collectionBaseURI; collectionInfo[index].collectionLibrary = _collectionLibrary; collectionInfo[index].collectionScript = _collectionScript; isCollectionCreated[index] = true; newCollectionIndex = index + 1; }

NextGenCore.sol#L130C1-L141C6

  1. In MinterContract.sol::airDropTokens() huge savings by caching constant value calls: gencore.viewTokensIndexMin(_collectionID), gencore.viewCirSupply(_collectionID) and gencore.viewTokensIndexMax(_collectionID).
function airDropTokens(address[] memory _recipients, string[] memory _tokenData, uint256[] memory _saltfun_o, uint256 _collectionID, uint256[] memory _numberOfTokens) public FunctionAdminRequired(this.airDropTokens.selector) { require(gencore.retrievewereDataAdded(_collectionID) == true, "Add data"); uint256 collectionTokenMintIndex; uint256 tokensIndexMin = gencore.viewTokensIndexMin(_collectionID); uint256 tokensIndexMax = gencore.viewTokensIndexMax(_collectionID); for (uint256 y=0; y< _recipients.length; y++) { uint256 circSupply = gencore.viewCirSupply(_collectionID); collectionTokenMintIndex = tokensIndexMin + circSupply + _numberOfTokens[y] - 1; require(collectionTokenMintIndex <= tokensIndexMax, "No supply"); for(uint256 i = 0; i < _numberOfTokens[y]; i++) { uint256 mintIndex = tokensIndexMin + circSupply + i; gencore.airDropTokens(mintIndex, _recipients[y], _tokenData[y], _saltfun_o[y], _collectionID); } } }

MinterContract.sol#L181C1-L192C6

  1. Unnecessary external call, reuse collectionTokenMintIndex. uint256 mintIndex = collectionTokenMintIndex; MinterContract.sol#L281

Initialize structs to storage to save gas for more than one update.

Ex:

function createCollection(string memory _collectionName, string memory _collectionArtist, string memory _collectionDescription, string memory _collectionWebsite, string memory _collectionLicense, string memory _collectionBaseURI, string memory _collectionLibrary, string[] memory _collectionScript) external FunctionAdminRequired(this.createCollection.selector) { uint256 index = newCollectionIndex; collectionInfoStructure storage info = collectionInfo[index]; info.collectionName = _collectionName; info.collectionArtist = _collectionArtist; info.collectionDescription = _collectionDescription; info.collectionWebsite = _collectionWebsite; info.collectionLicense = _collectionLicense; info.collectionBaseURI = _collectionBaseURI; info.collectionLibrary = _collectionLibrary; info.collectionScript = _collectionScript; isCollectionCreated[index] = true; newCollectionIndex = index + 1; }

Instances: setCollectionData(), createCollection(), addRandomizer(), airDropTokens(), mint(), burn(), updateCollectionInfo(), artistSignature(),

Unnecessary sloads

  1. newCollectionIndex = newCollectionIndex + 1 can be just newCollectionIndex = 1 as we know newCollectionIndex is 0.
    NextGenCore.solL#110

Public functions not used from inside the contract can be declared external.

  1. createCollection() NextGenCore.sol#L130
  2. setCollectionData() NextGenCore.sol#L147

Redundant code

  1. Require check is not needed in NextGenCore.sol::burn() as it already checks for token ownership and as far as I've seen there's only a possibility to mint tokens between reservedMinTokensIndex and reservedMaxTokensIndex. NextGenCore.sol#L206

#0 - 141345

2023-11-26T06:03:56Z

1914 0xSolus l r nc 1 0 3

G 1 n G 2 n G 3 l G 4 i G 5 n

#1 - c4-pre-sort

2023-11-26T06:04:45Z

141345 marked the issue as sufficient quality report

#2 - c4-judge

2023-12-02T17:37:24Z

alex-ppg marked the issue as grade-b

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