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
Rank: 107/243
Findings: 1
Award: $13.98
🌟 Selected for report: 0
🚀 Solo Findings: 0
13.9832 USDC - $13.98
a++
is more gas-efficient than a = a + 1
in Solidityunchecked
 block to save gasFile: smart-contracts/MinterContract.sol 258: function burnToMint(uint256 _burnCollectionID, uint256 _tokenId, uint256 _mintCollectionID, uint256 _saltfun_o) public payable { require(burnToMintCollections[_burnCollectionID][_mintCollectionID] == true, "Initialize burn"); require(block.timestamp >= collectionPhases[_mintCollectionID].publicStartTime && block.timestamp<=collectionPhases[_mintCollectionID].publicEndTime,"No minting"); require ((_tokenId >= gencore.viewTokensIndexMin(_burnCollectionID)) && (_tokenId <= gencore.viewTokensIndexMax(_burnCollectionID)), "col/token id error"); // minting new token uint256 collectionTokenMintIndex; collectionTokenMintIndex = gencore.viewTokensIndexMin(_mintCollectionID) + gencore.viewCirSupply(_mintCollectionID); require(collectionTokenMintIndex <= gencore.viewTokensIndexMax(_mintCollectionID), "No supply"); require(msg.value >= getPrice(_mintCollectionID), "Wrong ETH"); uint256 mintIndex = gencore.viewTokensIndexMin(_mintCollectionID) + gencore.viewCirSupply(_mintCollectionID); // burn and mint token address burner = msg.sender; //@audit gencore.burnToMint(mintIndex, _burnCollectionID, _tokenId, _mintCollectionID, _saltfun_o, burner); collectionTotalAmount[_mintCollectionID] = collectionTotalAmount[_mintCollectionID] + msg.value; }
File: smart-contracts/MinterContract.sol 258: function burnToMint(uint256 _burnCollectionID, uint256 _tokenId, uint256 _mintCollectionID, uint256 _saltfun_o) public payable { require(burnToMintCollections[_burnCollectionID][_mintCollectionID] == true, "Initialize burn"); require(block.timestamp >= collectionPhases[_mintCollectionID].publicStartTime && block.timestamp<=collectionPhases[_mintCollectionID].publicEndTime,"No minting"); require ((_tokenId >= gencore.viewTokensIndexMin(_burnCollectionID)) && (_tokenId <= gencore.viewTokensIndexMax(_burnCollectionID)), "col/token id error"); // minting new token uint256 collectionTokenMintIndex; collectionTokenMintIndex = gencore.viewTokensIndexMin(_mintCollectionID) + gencore.viewCirSupply(_mintCollectionID); require(collectionTokenMintIndex <= gencore.viewTokensIndexMax(_mintCollectionID), "No supply"); require(msg.value >= getPrice(_mintCollectionID), "Wrong ETH"); uint256 mintIndex = gencore.viewTokensIndexMin(_mintCollectionID) + gencore.viewCirSupply(_mintCollectionID); // burn and mint token - address burner = msg.sender; - gencore.burnToMint(mintIndex, _burnCollectionID, _tokenId, _mintCollectionID, _saltfun_o, burner); + gencore.burnToMint(mintIndex, _burnCollectionID, _tokenId, _mintCollectionID, _saltfun_o, msg.sender); collectionTotalAmount[_mintCollectionID] = collectionTotalAmount[_mintCollectionID] + msg.value; }
Consider making the stack variables before the loop which gonna save gas
File: smart-contracts/MinterContract.sol 188: uint256 mintIndex = gencore.viewTokensIndexMin(_collectionID) + gencore.viewCirSupply(_collectionID); //@audit
File: smart-contracts/MinterContract.sol 235: uint256 mintIndex = gencore.viewTokensIndexMin(col) + gencore.viewCirSupply(col); //@audit
File: smart-contracts/NextGenCore.sol 299: function setTokenHash(uint256 _collectionID, uint256 _mintIndex, bytes32 _hash) external { require(msg.sender == collectionAdditionalData[_collectionID].randomizerContract); require(tokenToHash[_mintIndex] == 0x0000000000000000000000000000000000000000000000000000000000000000); tokenToHash[_mintIndex] = _hash; //@audit }
File: smart-contracts/NextGenCore.sol 299: function setTokenHash(uint256 _collectionID, uint256 _mintIndex, bytes32 _hash) external { require(msg.sender == collectionAdditionalData[_collectionID].randomizerContract); - require(tokenToHash[_mintIndex] == 0x0000000000000000000000000000000000000000000000000000000000000000); + require(_hash == 0x0000000000000000000000000000000000000000000000000000000000000000); tokenToHash[_mintIndex] = _hash; //@audit }
File: smart-contracts/MinterContract.sol 189: gencore.airDropTokens(mintIndex, _recipients[y], _tokenData[y], _saltfun_o[y], _collectionID); //@audit back-to back external call
File: smart-contracts/MinterContract.sol 362: uint256 mintIndex = gencore.viewTokensIndexMin(col) + gencore.viewCirSupply(col); //@audit back to back external call
a++
is more gas-efficient than a = a + 1
in Solidity.The ++
operator is a shorthand increment operator that is optimized at the EVM (Ethereum Virtual Machine) level and typically results in lower gas costs.
Using a++
is a more concise way of expressing an increment operation, and it often compiles to more efficient bytecode. On the other hand, a = a + 1
involves an additional assignment operation, which may result in slightly higher gas costs due to the extra bytecode generated.
File: smart-contracts/NextGenCore.sol 140: newCollectionIndex = newCollectionIndex + 1; 183: tokensAirdropPerAddress[_collectionID][_recipient] = tokensAirdropPerAddress[_collectionID][_recipient] + 1; 195: tokensMintedAllowlistAddress[_collectionID][_mintingAddress] = tokensMintedAllowlistAddress[_collectionID][_mintingAddress] + 1; 197: tokensMintedPerAddress[_collectionID][_mintingAddress] = tokensMintedPerAddress[_collectionID][_mintingAddress] + 1; 208: burnAmount[_collectionID] = burnAmount[_collectionID] + 1; 221: burnAmount[_burnCollectionID] = burnAmount[_burnCollectionID] + 1;
Combine variable assignments to reduce the number of instructions and potentially save gas.
File: smart-contracts/MinterContract.sol 258: function burnToMint(uint256 _burnCollectionID, uint256 _tokenId, uint256 _mintCollectionID, uint256 _saltfun_o) public payable { require(burnToMintCollections[_burnCollectionID][_mintCollectionID] == true, "Initialize burn"); require(block.timestamp >= collectionPhases[_mintCollectionID].publicStartTime && block.timestamp<=collectionPhases[_mintCollectionID].publicEndTime,"No minting"); require ((_tokenId >= gencore.viewTokensIndexMin(_burnCollectionID)) && (_tokenId <= gencore.viewTokensIndexMax(_burnCollectionID)), "col/token id error"); // minting new token uint256 collectionTokenMintIndex; collectionTokenMintIndex = gencore.viewTokensIndexMin(_mintCollectionID) + gencore.viewCirSupply(_mintCollectionID); require(collectionTokenMintIndex <= gencore.viewTokensIndexMax(_mintCollectionID), "No supply"); require(msg.value >= getPrice(_mintCollectionID), "Wrong ETH"); uint256 mintIndex = gencore.viewTokensIndexMin(_mintCollectionID) + gencore.viewCirSupply(_mintCollectionID); //@audit // burn and mint token address burner = msg.sender; gencore.burnToMint(mintIndex, _burnCollectionID, _tokenId, _mintCollectionID, _saltfun_o, burner); collectionTotalAmount[_mintCollectionID] = collectionTotalAmount[_mintCollectionID] + msg.value; }
258: function burnToMint(uint256 _burnCollectionID, uint256 _tokenId, uint256 _mintCollectionID, uint256 _saltfun_o) public payable { require(burnToMintCollections[_burnCollectionID][_mintCollectionID] == true, "Initialize burn"); require(block.timestamp >= collectionPhases[_mintCollectionID].publicStartTime && block.timestamp<=collectionPhases[_mintCollectionID].publicEndTime,"No minting"); require ((_tokenId >= gencore.viewTokensIndexMin(_burnCollectionID)) && (_tokenId <= gencore.viewTokensIndexMax(_burnCollectionID)), "col/token id error"); // minting new token uint256 collectionTokenMintIndex; collectionTokenMintIndex = gencore.viewTokensIndexMin(_mintCollectionID) + gencore.viewCirSupply(_mintCollectionID); require(collectionTokenMintIndex <= gencore.viewTokensIndexMax(_mintCollectionID), "No supply"); require(msg.value >= getPrice(_mintCollectionID), "Wrong ETH"); - uint256 mintIndex = gencore.viewTokensIndexMin(_mintCollectionID) + gencore.viewCirSupply(_mintCollectionID); //@audit // burn and mint token address burner = msg.sender; - gencore.burnToMint(mintIndex, _burnCollectionID, _tokenId, _mintCollectionID, _saltfun_o, burner); + gencore.burnToMint(collectionTokenMintIndex, _burnCollectionID, _tokenId, _mintCollectionID, _saltfun_o, burner); collectionTotalAmount[_mintCollectionID] = collectionTotalAmount[_mintCollectionID] + msg.value; }
File: smart-contracts/MinterContract.sol 276: function mintAndAuction(address _recipient, string memory _tokenData, uint256 _saltfun_o, uint256 _collectionID, uint _auctionEndTime) public FunctionAdminRequired(this.mintAndAuction.selector) { require(gencore.retrievewereDataAdded(_collectionID) == true, "Add data"); uint256 collectionTokenMintIndex; collectionTokenMintIndex = gencore.viewTokensIndexMin(_collectionID) + gencore.viewCirSupply(_collectionID); require(collectionTokenMintIndex <= gencore.viewTokensIndexMax(_collectionID), "No supply"); uint256 mintIndex = gencore.viewTokensIndexMin(_collectionID) + gencore.viewCirSupply(_collectionID); //@audit gencore.airDropTokens(mintIndex, _recipient, _tokenData, _saltfun_o, _collectionID); uint timeOfLastMint; // check 1 per period if (lastMintDate[_collectionID] == 0) { // for public sale set the allowlist the same time as publicsale timeOfLastMint = collectionPhases[_collectionID].allowlistStartTime - collectionPhases[_collectionID].timePeriod; } else { timeOfLastMint = lastMintDate[_collectionID]; } // uint calculates if period has passed in order to allow minting uint tDiff = (block.timestamp - timeOfLastMint) / collectionPhases[_collectionID].timePeriod; // users are able to mint after a day passes require(tDiff>=1, "1 mint/period"); lastMintDate[_collectionID] = collectionPhases[_collectionID].allowlistStartTime + (collectionPhases[_collectionID].timePeriod * (gencore.viewCirSupply(_collectionID) - 1)); //@audit mintToAuctionData[mintIndex] = _auctionEndTime; mintToAuctionStatus[mintIndex] = true; }
File: smart-contracts/MinterContract.sol 276: function mintAndAuction(address _recipient, string memory _tokenData, uint256 _saltfun_o, uint256 _collectionID, uint _auctionEndTime) public FunctionAdminRequired(this.mintAndAuction.selector) { require(gencore.retrievewereDataAdded(_collectionID) == true, "Add data"); uint256 collectionTokenMintIndex; collectionTokenMintIndex = gencore.viewTokensIndexMin(_collectionID) + gencore.viewCirSupply(_collectionID); require(collectionTokenMintIndex <= gencore.viewTokensIndexMax(_collectionID), "No supply"); - uint256 mintIndex = gencore.viewTokensIndexMin(_collectionID) + gencore.viewCirSupply(_collectionID); //@audit + uint256 mintIndex = collectionTokenMintIndex; gencore.airDropTokens(mintIndex, _recipient, _tokenData, _saltfun_o, _collectionID); uint timeOfLastMint; // check 1 per period if (lastMintDate[_collectionID] == 0) { // for public sale set the allowlist the same time as publicsale timeOfLastMint = collectionPhases[_collectionID].allowlistStartTime - collectionPhases[_collectionID].timePeriod; } else { timeOfLastMint = lastMintDate[_collectionID]; } // uint calculates if period has passed in order to allow minting uint tDiff = (block.timestamp - timeOfLastMint) / collectionPhases[_collectionID].timePeriod; // users are able to mint after a day passes require(tDiff>=1, "1 mint/period"); lastMintDate[_collectionID] = collectionPhases[_collectionID].allowlistStartTime + (collectionPhases[_collectionID].timePeriod * (gencore.viewCirSupply(_collectionID) - 1)); //@audit mintToAuctionData[mintIndex] = _auctionEndTime; mintToAuctionStatus[mintIndex] = true; }
unchecked
 block to save gasnewCollectionIndex = newCollectionIndex + 1
 can use it as newCollectionIndex
 is uint256
:
File: smart-contracts/NextGenCore.sol 140: newCollectionIndex = newCollectionIndex + 1; //@audit use unchecked
#0 - 141345
2023-11-26T06:03:16Z
1739 dharma09 l r nc 3 0 1
G 1 n G 2 l G 3 l G 4 i G 5 i G 6 l G 7 i
#1 - c4-pre-sort
2023-11-26T06:04:43Z
141345 marked the issue as sufficient quality report
#2 - alex-ppg
2023-12-02T17:49:50Z
G-01 is G-21
#3 - c4-judge
2023-12-02T17:49:55Z
alex-ppg marked the issue as grade-b