Infinity NFT Marketplace contest - Kaiziron's results

The world's most advanced NFT marketplace.

General Information

Platform: Code4rena

Start Date: 14/06/2022

Pot Size: $50,000 USDC

Total HM: 19

Participants: 99

Period: 5 days

Judge: HardlyDifficult

Total Solo HM: 4

Id: 136

League: ETH

Infinity NFT Marketplace

Findings Distribution

Researcher Performance

Rank: 59/99

Findings: 2

Award: $80.28

🌟 Selected for report: 0

🚀 Solo Findings: 0

Too many digits

Information : Too many digits

Instances include :

InfinityExchange.cancelAllOrders(uint256) (contracts/core/InfinityExchange.sol#379-384) uses literals with too many digits: - require(bool,string)(minNonce < userMinOrderNonce[msg.sender] + 1000000,too many) (contracts/core/InfinityExchange.sol#381)

Recommendation

Use the scientific notation


Variable names too similar

Information : Variable names too similar

Instances include :

Variable InfinityExchange.MATCH_EXECUTOR (contracts/core/InfinityExchange.sol#59) is too similar to InfinityExchange.updateMatchExecutor(address)._matchExecutor (contracts/core/InfinityExchange.sol#1255) Variable InfinityExchange.MATCH_EXECUTOR (contracts/core/InfinityExchange.sol#59) is too similar to InfinityExchange.constructor(address,address)._matchExecutor (contracts/core/InfinityExchange.sol#104) Variable InfinityExchange._matchOneToOneOrders(OrderTypes.MakerOrder,OrderTypes.MakerOrder,uint256,uint256,uint16,uint32,address).makerOrder1 (contracts/core/InfinityExchange.sol#575) is too similar to InfinityExchange._matchOneToOneOrders(OrderTypes.MakerOrder,OrderTypes.MakerOrder,uint256,uint256,uint16,uint32,address).makerOrder2 (contracts/core/InfinityExchange.sol#576) Variable InfinityExchange._matchOneToOneOrders(OrderTypes.MakerOrder,OrderTypes.MakerOrder,uint256,uint256,uint16,uint32,address).makerOrder1 (contracts/core/InfinityExchange.sol#575) is too similar to InfinityExchange.takeOrders(OrderTypes.MakerOrder[],OrderTypes.OrderItem[][]).makerOrders (contracts/core/InfinityExchange.sol#336) Variable InfinityExchange._matchOneToOneOrders(OrderTypes.MakerOrder,OrderTypes.MakerOrder,uint256,uint256,uint16,uint32,address).makerOrder1 (contracts/core/InfinityExchange.sol#575) is too similar to InfinityExchange.takeMultipleOneOrders(OrderTypes.MakerOrder[]).makerOrders (contracts/core/InfinityExchange.sol#300) Variable InfinityExchange._matchOneToOneOrders(OrderTypes.MakerOrder,OrderTypes.MakerOrder,uint256,uint256,uint16,uint32,address).makerOrder2 (contracts/core/InfinityExchange.sol#576) is too similar to InfinityExchange.takeMultipleOneOrders(OrderTypes.MakerOrder[]).makerOrders (contracts/core/InfinityExchange.sol#300) Variable InfinityExchange._matchOneToOneOrders(OrderTypes.MakerOrder,OrderTypes.MakerOrder,uint256,uint256,uint16,uint32,address).makerOrder2 (contracts/core/InfinityExchange.sol#576) is too similar to InfinityExchange.takeOrders(OrderTypes.MakerOrder[],OrderTypes.OrderItem[][]).makerOrders (contracts/core/InfinityExchange.sol#336) Variable InfinityExchange.matchOneToOneOrders(OrderTypes.MakerOrder[],OrderTypes.MakerOrder[]).makerOrders1 (contracts/core/InfinityExchange.sol#133) is too similar to InfinityExchange.matchOneToOneOrders(OrderTypes.MakerOrder[],OrderTypes.MakerOrder[]).makerOrders2 (contracts/core/InfinityExchange.sol#134) Variable InfinityOrderBookComplication.doTokenIdsIntersect(OrderTypes.OrderItem,OrderTypes.OrderItem).item1TokensLength (contracts/core/InfinityOrderBookComplication.sol#283) is too similar to InfinityOrderBookComplication.doTokenIdsIntersect(OrderTypes.OrderItem,OrderTypes.OrderItem).item2TokensLength (contracts/core/InfinityOrderBookComplication.sol#284) Variable IComplication.canExecMatchOneToOne(OrderTypes.MakerOrder,OrderTypes.MakerOrder).makerOrder1 (contracts/interfaces/IComplication.sol#24) is too similar to IComplication.canExecMatchOneToOne(OrderTypes.MakerOrder,OrderTypes.MakerOrder).makerOrder2 (contracts/interfaces/IComplication.sol#24) Variable InfinityOrderBookComplication.canExecMatchOneToOne(OrderTypes.MakerOrder,OrderTypes.MakerOrder).makerOrder1 (contracts/core/InfinityOrderBookComplication.sol#26) is too similar to InfinityOrderBookComplication.canExecMatchOneToOne(OrderTypes.MakerOrder,OrderTypes.MakerOrder).makerOrder2 (contracts/core/InfinityOrderBookComplication.sol#26) Variable IComplication.canExecMatchOneToOne(OrderTypes.MakerOrder,OrderTypes.MakerOrder).makerOrder1 (contracts/interfaces/IComplication.sol#24) is too similar to InfinityOrderBookComplication.canExecMatchOneToOne(OrderTypes.MakerOrder,OrderTypes.MakerOrder).makerOrder2 (contracts/core/InfinityOrderBookComplication.sol#26) Variable InfinityOrderBookComplication.canExecMatchOneToOne(OrderTypes.MakerOrder,OrderTypes.MakerOrder).makerOrder1Price (contracts/core/InfinityOrderBookComplication.sol#43) is too similar to InfinityOrderBookComplication.canExecMatchOneToOne(OrderTypes.MakerOrder,OrderTypes.MakerOrder).makerOrder2Price (contracts/core/InfinityOrderBookComplication.sol#44) Variable InfinityOrderBookComplication.canExecMatchOneToOne(OrderTypes.MakerOrder,OrderTypes.MakerOrder).makerOrder1 (contracts/core/InfinityOrderBookComplication.sol#26) is too similar to IComplication.canExecMatchOneToOne(OrderTypes.MakerOrder,OrderTypes.MakerOrder).makerOrder2 (contracts/interfaces/IComplication.sol#24) Variable InfinityOrderBookComplication.doItemsIntersect(OrderTypes.OrderItem[],OrderTypes.OrderItem[]).order1NftsLength (contracts/core/InfinityOrderBookComplication.sol#237) is too similar to InfinityOrderBookComplication.doItemsIntersect(OrderTypes.OrderItem[],OrderTypes.OrderItem[]).order2NftsLength (contracts/core/InfinityOrderBookComplication.sol#238) Variable InfinityStaker.INFINITY_TREASURY (contracts/staking/InfinityStaker.sol#27) is too similar to InfinityStaker.updateInfinityTreasury(address)._infinityTreasury (contracts/staking/InfinityStaker.sol#375) Variable InfinityStaker.INFINITY_TREASURY (contracts/staking/InfinityStaker.sol#27) is too similar to InfinityStaker.constructor(address,address)._infinityTreasury (contracts/staking/InfinityStaker.sol#49)

Recommendation

Prevent variables from having similar names.


Conformance to Solidity naming conventions

Information : Conformance to Solidity naming conventions Naming convention

Instances include :

Function ERC20Permit.DOMAIN_SEPARATOR() (node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol#73-75) is not in mixedCase Variable ERC20Permit._PERMIT_TYPEHASH (node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol#28-29) is not in mixedCase Function IERC20Permit.DOMAIN_SEPARATOR() (node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol#59) is not in mixedCase Parameter ERC721.safeTransferFrom(address,address,uint256,bytes)._data (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#179) is not in mixedCase Variable EIP712._CACHED_DOMAIN_SEPARATOR (node_modules/@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol#31) is not in mixedCase Variable EIP712._CACHED_CHAIN_ID (node_modules/@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol#32) is not in mixedCase Variable EIP712._CACHED_THIS (node_modules/@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol#33) is not in mixedCase Variable EIP712._HASHED_NAME (node_modules/@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol#35) is not in mixedCase Variable EIP712._HASHED_VERSION (node_modules/@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol#36) is not in mixedCase Variable EIP712._TYPE_HASH (node_modules/@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol#37) is not in mixedCase Parameter InfinityExchange.addCurrency(address)._currency (contracts/core/InfinityExchange.sol#1235) is not in mixedCase Parameter InfinityExchange.addComplication(address)._complication (contracts/core/InfinityExchange.sol#1240) is not in mixedCase Parameter InfinityExchange.removeCurrency(address)._currency (contracts/core/InfinityExchange.sol#1245) is not in mixedCase Parameter InfinityExchange.removeComplication(address)._complication (contracts/core/InfinityExchange.sol#1250) is not in mixedCase Parameter InfinityExchange.updateMatchExecutor(address)._matchExecutor (contracts/core/InfinityExchange.sol#1255) is not in mixedCase Parameter InfinityExchange.updateWethTranferGas(uint32)._wethTransferGasUnits (contracts/core/InfinityExchange.sol#1260) is not in mixedCase Parameter InfinityExchange.setProtocolFee(uint16)._protocolFeeBps (contracts/core/InfinityExchange.sol#1266) is not in mixedCase Variable InfinityExchange.WETH (contracts/core/InfinityExchange.sol#55) is not in mixedCase Variable InfinityExchange.DOMAIN_SEPARATOR (contracts/core/InfinityExchange.sol#57) is not in mixedCase Variable InfinityExchange.MATCH_EXECUTOR (contracts/core/InfinityExchange.sol#59) is not in mixedCase Variable InfinityExchange.WETH_TRANSFER_GAS_UNITS (contracts/core/InfinityExchange.sol#61) is not in mixedCase Variable InfinityExchange.PROTOCOL_FEE_BPS (contracts/core/InfinityExchange.sol#63) is not in mixedCase Parameter InfinityStaker.updateInfinityTreasury(address)._infinityTreasury (contracts/staking/InfinityStaker.sol#375) is not in mixedCase Variable InfinityStaker.INFINITY_TOKEN (contracts/staking/InfinityStaker.sol#25) is not in mixedCase Variable InfinityStaker.INFINITY_TREASURY (contracts/staking/InfinityStaker.sol#27) is not in mixedCase Variable InfinityStaker.BRONZE_STAKE_THRESHOLD (contracts/staking/InfinityStaker.sol#33) is not in mixedCase Variable InfinityStaker.SILVER_STAKE_THRESHOLD (contracts/staking/InfinityStaker.sol#34) is not in mixedCase Variable InfinityStaker.GOLD_STAKE_THRESHOLD (contracts/staking/InfinityStaker.sol#35) is not in mixedCase Variable InfinityStaker.PLATINUM_STAKE_THRESHOLD (contracts/staking/InfinityStaker.sol#36) is not in mixedCase Variable InfinityStaker.THREE_MONTH_PENALTY (contracts/staking/InfinityStaker.sol#40) is not in mixedCase Variable InfinityStaker.SIX_MONTH_PENALTY (contracts/staking/InfinityStaker.sol#41) is not in mixedCase Variable InfinityStaker.TWELVE_MONTH_PENALTY (contracts/staking/InfinityStaker.sol#42) is not in mixedCase Variable TimelockConfig._config (contracts/token/TimelockConfig.sol#28) is not in mixedCase Variable TimelockConfig._configSet (contracts/token/TimelockConfig.sol#29) is not in mixedCase Variable TimelockConfig._pending (contracts/token/TimelockConfig.sol#31) is not in mixedCase Variable TimelockConfig._pendingSet (contracts/token/TimelockConfig.sol#32) is not in mixedCase

Recommendation

Follow the Solidity naming convention.


Low-level calls

Information : Low-level calls

Instances include :

Low level call in Address.sendValue(address,uint256) (node_modules/@openzeppelin/contracts/utils/Address.sol#60-65): - (success) = recipient.call{value: amount}() (node_modules/@openzeppelin/contracts/utils/Address.sol#63) Low level call in Address.functionCallWithValue(address,bytes,uint256,string) (node_modules/@openzeppelin/contracts/utils/Address.sol#128-139): - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) Low level call in Address.functionStaticCall(address,bytes,string) (node_modules/@openzeppelin/contracts/utils/Address.sol#157-166): - (success,returndata) = target.staticcall(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#164) Low level call in Address.functionDelegateCall(address,bytes,string) (node_modules/@openzeppelin/contracts/utils/Address.sol#184-193): - (success,returndata) = target.delegatecall(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#191) Low level call in InfinityExchange._transferFees(address,address,uint256,address) (contracts/core/InfinityExchange.sol#1128-1148): - (sent) = seller.call{value: remainingAmount}() (contracts/core/InfinityExchange.sol#1140) Low level call in InfinityExchange.rescueETH(address) (contracts/core/InfinityExchange.sol#1229-1232): - (sent) = destination.call{value: msg.value}() (contracts/core/InfinityExchange.sol#1230) Low level call in InfinityStaker.rescueETH(address) (contracts/staking/InfinityStaker.sol#345-348): - (sent) = destination.call{value: msg.value}() (contracts/staking/InfinityStaker.sol#346)

Recommendation

Avoid low-level calls. Check the call success. If the call is meant for a contract, check for code existence.


Incorrect versions of Solidity

solc-0.8.14 is not recommended for deployment

Information : Incorrect versions of Solidity

Instances include :

Pragma version0.8.14 (contracts/MockERC20.sol#2) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7 Pragma version0.8.14 (contracts/MockERC721.sol#2) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7 Pragma version0.8.14 (contracts/core/InfinityExchange.sol#2) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7 Pragma version0.8.14 (contracts/core/InfinityOrderBookComplication.sol#2) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7 Pragma version0.8.14 (contracts/interfaces/IComplication.sol#2) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7 Pragma version0.8.14 (contracts/interfaces/IStaker.sol#2) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7 Pragma version0.8.14 (contracts/libs/OrderTypes.sol#2) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7 Pragma version0.8.14 (contracts/libs/SignatureChecker.sol#2) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7 Pragma version0.8.14 (contracts/staking/InfinityStaker.sol#2) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7 Pragma version0.8.14 (contracts/token/InfinityToken.sol#2) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7 Pragma version0.8.14 (contracts/token/TimelockConfig.sol#2) necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7

Recommendation

Consider deploying with 0.6.12/0.7.6/0.8.7


Block timestamp

Information : Block timestamp

Instances include :

InfinityExchange.takeMultipleOneOrders(OrderTypes.MakerOrder[]) (contracts/core/InfinityExchange.sol#300-328) uses timestamp for comparisons Dangerous comparisons: - isTimeValid = makerOrders[i].constraints[3] <= block.timestamp && makerOrders[i].constraints[4] >= block.timestamp (contracts/core/InfinityExchange.sol#311-312) - require(bool,string)(isTimeValid,invalid time) (contracts/core/InfinityExchange.sol#313) - require(bool,string)(msg.value >= totalPrice,invalid total price) (contracts/core/InfinityExchange.sol#326) InfinityExchange.takeOrders(OrderTypes.MakerOrder[],OrderTypes.OrderItem[][]) (contracts/core/InfinityExchange.sol#336-364) uses timestamp for comparisons Dangerous comparisons: - require(bool,string)(msg.value >= totalPrice,invalid total price) (contracts/core/InfinityExchange.sol#362) InfinityExchange._transferFees(address,address,uint256,address) (contracts/core/InfinityExchange.sol#1128-1148) uses timestamp for comparisons Dangerous comparisons: - require(bool,string)(sent,failed to send ether to seller) (contracts/core/InfinityExchange.sol#1141) InfinityExchange._getCurrentPrice(OrderTypes.MakerOrder) (contracts/core/InfinityExchange.sol#1153-1165) uses timestamp for comparisons Dangerous comparisons: - priceDiff == 0 || duration == 0 (contracts/core/InfinityExchange.sol#1157) - elapsedTime > duration (contracts/core/InfinityExchange.sol#1162) InfinityOrderBookComplication.canExecMatchOneToOne(OrderTypes.MakerOrder,OrderTypes.MakerOrder) (contracts/core/InfinityOrderBookComplication.sol#26-57) uses timestamp for comparisons Dangerous comparisons: - _isTimeValid = makerOrder2.constraints[3] <= block.timestamp && makerOrder2.constraints[4] >= block.timestamp && makerOrder1.constraints[3] <= block.timestamp && makerOrder1.constraints[4] >= block.timestamp (contracts/core/InfinityOrderBookComplication.sol#38-41) - _isPriceValid = makerOrder2Price >= makerOrder1Price (contracts/core/InfinityOrderBookComplication.sol#47) - _isPriceValid = makerOrder1Price >= makerOrder2Price (contracts/core/InfinityOrderBookComplication.sol#50) - (numItemsValid && _isTimeValid && doItemsIntersect(makerOrder1.nfts,makerOrder2.nfts) && _isPriceValid,execPrice) (contracts/core/InfinityOrderBookComplication.sol#53-56) InfinityOrderBookComplication.canExecMatchOneToMany(OrderTypes.MakerOrder,OrderTypes.MakerOrder[]) (contracts/core/InfinityOrderBookComplication.sol#68-116) uses timestamp for comparisons Dangerous comparisons: - ! isOrdersTimeValid || ! itemsIntersect (contracts/core/InfinityOrderBookComplication.sol#77) - isOrdersTimeValid = isOrdersTimeValid && manyMakerOrders[i].constraints[3] <= block.timestamp && manyMakerOrders[i].constraints[4] >= block.timestamp (contracts/core/InfinityOrderBookComplication.sol#89-92) - _isTimeValid = isOrdersTimeValid && makerOrder.constraints[3] <= block.timestamp && makerOrder.constraints[4] >= block.timestamp (contracts/core/InfinityOrderBookComplication.sol#101-103) - _isPriceValid = sumCurrentOrderPrices >= currentMakerOrderPrice (contracts/core/InfinityOrderBookComplication.sol#110) - _isPriceValid = sumCurrentOrderPrices <= currentMakerOrderPrice (contracts/core/InfinityOrderBookComplication.sol#112) - (numItems == makerOrder.constraints[0]) && _isTimeValid && itemsIntersect && _isPriceValid (contracts/core/InfinityOrderBookComplication.sol#115) InfinityOrderBookComplication.canExecMatchOrder(OrderTypes.MakerOrder,OrderTypes.MakerOrder,OrderTypes.OrderItem[]) (contracts/core/InfinityOrderBookComplication.sol#128-143) uses timestamp for comparisons Dangerous comparisons: - (isTimeValid(sell,buy) && _isPriceValid && areNumItemsValid(sell,buy,constructedNfts) && doItemsIntersect(sell.nfts,constructedNfts) && doItemsIntersect(buy.nfts,constructedNfts) && doItemsIntersect(sell.nfts,buy.nfts),execPrice) (contracts/core/InfinityOrderBookComplication.sol#134-142) InfinityOrderBookComplication.canExecTakeOrder(OrderTypes.MakerOrder,OrderTypes.OrderItem[]) (contracts/core/InfinityOrderBookComplication.sol#154-164) uses timestamp for comparisons Dangerous comparisons: - (makerOrder.constraints[3] <= block.timestamp && makerOrder.constraints[4] >= block.timestamp && areTakerNumItemsValid(makerOrder,takerItems) && doItemsIntersect(makerOrder.nfts,takerItems)) (contracts/core/InfinityOrderBookComplication.sol#160-163) InfinityOrderBookComplication.isTimeValid(OrderTypes.MakerOrder,OrderTypes.MakerOrder) (contracts/core/InfinityOrderBookComplication.sol#169-179) uses timestamp for comparisons Dangerous comparisons: - sell.constraints[3] <= block.timestamp && sell.constraints[4] >= block.timestamp && buy.constraints[3] <= block.timestamp && buy.constraints[4] >= block.timestamp (contracts/core/InfinityOrderBookComplication.sol#174-178) InfinityOrderBookComplication.isPriceValid(OrderTypes.MakerOrder,OrderTypes.MakerOrder) (contracts/core/InfinityOrderBookComplication.sol#182-189) uses timestamp for comparisons Dangerous comparisons: - (currentBuyPrice >= currentSellPrice,currentSellPrice) (contracts/core/InfinityOrderBookComplication.sol#188) InfinityOrderBookComplication._getCurrentPrice(OrderTypes.MakerOrder) (contracts/core/InfinityOrderBookComplication.sol#330-342) uses timestamp for comparisons Dangerous comparisons: - priceDiff == 0 || duration == 0 (contracts/core/InfinityOrderBookComplication.sol#334) - elapsedTime > duration (contracts/core/InfinityOrderBookComplication.sol#339) InfinityStaker.getVestedAmount(address,Duration) (contracts/staking/InfinityStaker.sol#260-271) uses timestamp for comparisons Dangerous comparisons: - secondsSinceStake >= durationInSeconds (contracts/staking/InfinityStaker.sol#270) InfinityToken.advanceEpoch() (contracts/token/InfinityToken.sol#60-82) uses timestamp for comparisons Dangerous comparisons: - require(bool,string)(currentEpoch < getMaxEpochs(),no epochs left) (contracts/token/InfinityToken.sol#61) - require(bool,string)(block.timestamp >= currentEpochTimestamp + getCliff(),cliff not passed) (contracts/token/InfinityToken.sol#62) - require(bool,string)(block.timestamp >= previousEpochTimestamp + getEpochDuration(),not ready to advance) (contracts/token/InfinityToken.sol#63) - epochsPassedSinceLastAdvance > epochsLeft (contracts/token/InfinityToken.sol#67-69) TimelockConfig.confirmChange(bytes32) (contracts/token/TimelockConfig.sol#50-62) uses timestamp for comparisons Dangerous comparisons: - require(bool,string)(block.timestamp >= _pending[configId].timestamp + _config[TIMELOCK],too early) (contracts/token/TimelockConfig.sol#52)

Recommendation

Avoid relying on block.timestamp.


Reentrancy vulnerabilities

Information : reentrancy-events check-effects-interactions pattern

Instances include :

Reentrancy in InfinityExchange._execMatchOneMakerBuyToManyMakerSells(bytes32,bytes32,OrderTypes.MakerOrder,OrderTypes.MakerOrder,uint256,uint16) (contracts/core/InfinityExchange.sol#810-832): External calls: - _execMatchOneToManyOrders(sell.signer,buy.signer,sell.nfts,buy.execParams[1],remainingAmount) (contracts/core/InfinityExchange.sol#821) - returndata = address(token).functionCall(data,SafeERC20: low-level call failed) (node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol#93) - IERC20(currency).safeTransferFrom(buyer,seller,amount) (contracts/core/InfinityExchange.sol#844) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) - IERC721(item.collection).safeTransferFrom(from,to,item.tokens[i].tokenId) (contracts/core/InfinityExchange.sol#1087) - IERC1155(item.collection).safeBatchTransferFrom(from,to,tokenIdsArr,numTokensPerTokenIdArr,0x0) (contracts/core/InfinityExchange.sol#1116) External calls sending eth: - _execMatchOneToManyOrders(sell.signer,buy.signer,sell.nfts,buy.execParams[1],remainingAmount) (contracts/core/InfinityExchange.sol#821) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) Event emitted after the call(s): - MatchOrderFulfilled(sellOrderHash,buyOrderHash,seller,buyer,complication,currency,amount) (contracts/core/InfinityExchange.sol#931) - _emitMatchEvent(sellOrderHash,buyOrderHash,sell.signer,buy.signer,buy.execParams[0],buy.execParams[1],execPrice) (contracts/core/InfinityExchange.sol#822-830) Reentrancy in InfinityExchange._execMatchOneMakerSellToManyMakerBuys(bytes32,bytes32,OrderTypes.MakerOrder,OrderTypes.MakerOrder,uint256,uint256,uint16,uint32,address) (contracts/core/InfinityExchange.sol#763-796): External calls: - _execMatchOneToManyOrders(sell.signer,buy.signer,buy.nfts,buy.execParams[1],remainingAmount) (contracts/core/InfinityExchange.sol#777) - returndata = address(token).functionCall(data,SafeERC20: low-level call failed) (node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol#93) - IERC20(currency).safeTransferFrom(buyer,seller,amount) (contracts/core/InfinityExchange.sol#844) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) - IERC721(item.collection).safeTransferFrom(from,to,item.tokens[i].tokenId) (contracts/core/InfinityExchange.sol#1087) - IERC1155(item.collection).safeBatchTransferFrom(from,to,tokenIdsArr,numTokensPerTokenIdArr,0x0) (contracts/core/InfinityExchange.sol#1116) External calls sending eth: - _execMatchOneToManyOrders(sell.signer,buy.signer,buy.nfts,buy.execParams[1],remainingAmount) (contracts/core/InfinityExchange.sol#777) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) Event emitted after the call(s): - MatchOrderFulfilled(sellOrderHash,buyOrderHash,seller,buyer,complication,currency,amount) (contracts/core/InfinityExchange.sol#931) - _emitMatchEvent(sellOrderHash,buyOrderHash,sell.signer,buy.signer,buy.execParams[0],buy.execParams[1],execPrice) (contracts/core/InfinityExchange.sol#778-786) Reentrancy in InfinityExchange._execMatchOneToOneOrders(bytes32,bytes32,OrderTypes.MakerOrder,OrderTypes.MakerOrder,uint256,uint256,uint16,uint32,address) (contracts/core/InfinityExchange.sol#712-748): External calls: - _transferMultipleNFTs(sell.signer,buy.signer,sell.nfts) (contracts/core/InfinityExchange.sol#727) - IERC721(item.collection).safeTransferFrom(from,to,item.tokens[i].tokenId) (contracts/core/InfinityExchange.sol#1087) - IERC1155(item.collection).safeBatchTransferFrom(from,to,tokenIdsArr,numTokensPerTokenIdArr,0x0) (contracts/core/InfinityExchange.sol#1116) - IERC20(buy.execParams[1]).safeTransferFrom(buy.signer,sell.signer,remainingAmount) (contracts/core/InfinityExchange.sol#729) Event emitted after the call(s): - MatchOrderFulfilled(sellOrderHash,buyOrderHash,seller,buyer,complication,currency,amount) (contracts/core/InfinityExchange.sol#931) - _emitMatchEvent(sellOrderHash,buyOrderHash,sell.signer,buy.signer,buy.execParams[0],buy.execParams[1],execPrice) (contracts/core/InfinityExchange.sol#730-738) Reentrancy in InfinityExchange._execMatchOrders(bytes32,bytes32,OrderTypes.MakerOrder,OrderTypes.MakerOrder,OrderTypes.OrderItem[],uint256,uint256,uint16,uint32,address) (contracts/core/InfinityExchange.sol#861-902): External calls: - _execMatchOrder(sell.signer,buy.signer,sell.constraints[5],buy.constraints[5],constructedNfts,buy.execParams[1],remainingAmount) (contracts/core/InfinityExchange.sol#875-883) - returndata = address(token).functionCall(data,SafeERC20: low-level call failed) (node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol#93) - IERC20(currency).safeTransferFrom(buyer,seller,amount) (contracts/core/InfinityExchange.sol#919) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) - IERC721(item.collection).safeTransferFrom(from,to,item.tokens[i].tokenId) (contracts/core/InfinityExchange.sol#1087) - IERC1155(item.collection).safeBatchTransferFrom(from,to,tokenIdsArr,numTokensPerTokenIdArr,0x0) (contracts/core/InfinityExchange.sol#1116) External calls sending eth: - _execMatchOrder(sell.signer,buy.signer,sell.constraints[5],buy.constraints[5],constructedNfts,buy.execParams[1],remainingAmount) (contracts/core/InfinityExchange.sol#875-883) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) Event emitted after the call(s): - MatchOrderFulfilled(sellOrderHash,buyOrderHash,seller,buyer,complication,currency,amount) (contracts/core/InfinityExchange.sol#931) - _emitMatchEvent(sellOrderHash,buyOrderHash,sell.signer,buy.signer,buy.execParams[0],buy.execParams[1],execPrice) (contracts/core/InfinityExchange.sol#884-892) Reentrancy in InfinityExchange._execTakeOneOrder(bytes32,OrderTypes.MakerOrder,bool,uint256) (contracts/core/InfinityExchange.sol#989-1003): External calls: - _transferNFTsAndFees(makerOrder.signer,msg.sender,makerOrder.nfts,execPrice,makerOrder.execParams[1]) (contracts/core/InfinityExchange.sol#997) - returndata = address(token).functionCall(data,SafeERC20: low-level call failed) (node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol#93) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) - (sent) = seller.call{value: remainingAmount}() (contracts/core/InfinityExchange.sol#1140) - IERC721(item.collection).safeTransferFrom(from,to,item.tokens[i].tokenId) (contracts/core/InfinityExchange.sol#1087) - IERC20(currency).safeTransferFrom(buyer,seller,remainingAmount) (contracts/core/InfinityExchange.sol#1144) - IERC20(currency).safeTransferFrom(buyer,address(this),protocolFee) (contracts/core/InfinityExchange.sol#1146) - IERC1155(item.collection).safeBatchTransferFrom(from,to,tokenIdsArr,numTokensPerTokenIdArr,0x0) (contracts/core/InfinityExchange.sol#1116) External calls sending eth: - _transferNFTsAndFees(makerOrder.signer,msg.sender,makerOrder.nfts,execPrice,makerOrder.execParams[1]) (contracts/core/InfinityExchange.sol#997) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) - (sent) = seller.call{value: remainingAmount}() (contracts/core/InfinityExchange.sol#1140) Event emitted after the call(s): - TakeOrderFulfilled(orderHash,seller,buyer,order.execParams[0],order.execParams[1],amount) (contracts/core/InfinityExchange.sol#1012) - _emitTakerEvent(makerOrderHash,makerOrder.signer,msg.sender,makerOrder,execPrice) (contracts/core/InfinityExchange.sol#998) Reentrancy in InfinityExchange._execTakeOneOrder(bytes32,OrderTypes.MakerOrder,bool,uint256) (contracts/core/InfinityExchange.sol#989-1003): External calls: - _transferNFTsAndFees(msg.sender,makerOrder.signer,makerOrder.nfts,execPrice,makerOrder.execParams[1]) (contracts/core/InfinityExchange.sol#1000) - returndata = address(token).functionCall(data,SafeERC20: low-level call failed) (node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol#93) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) - (sent) = seller.call{value: remainingAmount}() (contracts/core/InfinityExchange.sol#1140) - IERC721(item.collection).safeTransferFrom(from,to,item.tokens[i].tokenId) (contracts/core/InfinityExchange.sol#1087) - IERC20(currency).safeTransferFrom(buyer,seller,remainingAmount) (contracts/core/InfinityExchange.sol#1144) - IERC20(currency).safeTransferFrom(buyer,address(this),protocolFee) (contracts/core/InfinityExchange.sol#1146) - IERC1155(item.collection).safeBatchTransferFrom(from,to,tokenIdsArr,numTokensPerTokenIdArr,0x0) (contracts/core/InfinityExchange.sol#1116) External calls sending eth: - _transferNFTsAndFees(msg.sender,makerOrder.signer,makerOrder.nfts,execPrice,makerOrder.execParams[1]) (contracts/core/InfinityExchange.sol#1000) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) - (sent) = seller.call{value: remainingAmount}() (contracts/core/InfinityExchange.sol#1140) Event emitted after the call(s): - TakeOrderFulfilled(orderHash,seller,buyer,order.execParams[0],order.execParams[1],amount) (contracts/core/InfinityExchange.sol#1012) - _emitTakerEvent(makerOrderHash,msg.sender,makerOrder.signer,makerOrder,execPrice) (contracts/core/InfinityExchange.sol#1001) Reentrancy in InfinityExchange._execTakeOrders(bytes32,OrderTypes.MakerOrder,OrderTypes.OrderItem[],bool,uint256) (contracts/core/InfinityExchange.sol#963-978): External calls: - _transferNFTsAndFees(makerOrder.signer,msg.sender,takerItems,execPrice,makerOrder.execParams[1]) (contracts/core/InfinityExchange.sol#972) - returndata = address(token).functionCall(data,SafeERC20: low-level call failed) (node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol#93) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) - (sent) = seller.call{value: remainingAmount}() (contracts/core/InfinityExchange.sol#1140) - IERC721(item.collection).safeTransferFrom(from,to,item.tokens[i].tokenId) (contracts/core/InfinityExchange.sol#1087) - IERC20(currency).safeTransferFrom(buyer,seller,remainingAmount) (contracts/core/InfinityExchange.sol#1144) - IERC20(currency).safeTransferFrom(buyer,address(this),protocolFee) (contracts/core/InfinityExchange.sol#1146) - IERC1155(item.collection).safeBatchTransferFrom(from,to,tokenIdsArr,numTokensPerTokenIdArr,0x0) (contracts/core/InfinityExchange.sol#1116) External calls sending eth: - _transferNFTsAndFees(makerOrder.signer,msg.sender,takerItems,execPrice,makerOrder.execParams[1]) (contracts/core/InfinityExchange.sol#972) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) - (sent) = seller.call{value: remainingAmount}() (contracts/core/InfinityExchange.sol#1140) Event emitted after the call(s): - TakeOrderFulfilled(orderHash,seller,buyer,order.execParams[0],order.execParams[1],amount) (contracts/core/InfinityExchange.sol#1012) - _emitTakerEvent(makerOrderHash,makerOrder.signer,msg.sender,makerOrder,execPrice) (contracts/core/InfinityExchange.sol#973) Reentrancy in InfinityExchange._execTakeOrders(bytes32,OrderTypes.MakerOrder,OrderTypes.OrderItem[],bool,uint256) (contracts/core/InfinityExchange.sol#963-978): External calls: - _transferNFTsAndFees(msg.sender,makerOrder.signer,takerItems,execPrice,makerOrder.execParams[1]) (contracts/core/InfinityExchange.sol#975) - returndata = address(token).functionCall(data,SafeERC20: low-level call failed) (node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol#93) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) - (sent) = seller.call{value: remainingAmount}() (contracts/core/InfinityExchange.sol#1140) - IERC721(item.collection).safeTransferFrom(from,to,item.tokens[i].tokenId) (contracts/core/InfinityExchange.sol#1087) - IERC20(currency).safeTransferFrom(buyer,seller,remainingAmount) (contracts/core/InfinityExchange.sol#1144) - IERC20(currency).safeTransferFrom(buyer,address(this),protocolFee) (contracts/core/InfinityExchange.sol#1146) - IERC1155(item.collection).safeBatchTransferFrom(from,to,tokenIdsArr,numTokensPerTokenIdArr,0x0) (contracts/core/InfinityExchange.sol#1116) External calls sending eth: - _transferNFTsAndFees(msg.sender,makerOrder.signer,takerItems,execPrice,makerOrder.execParams[1]) (contracts/core/InfinityExchange.sol#975) - (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) - (sent) = seller.call{value: remainingAmount}() (contracts/core/InfinityExchange.sol#1140) Event emitted after the call(s): - TakeOrderFulfilled(orderHash,seller,buyer,order.execParams[0],order.execParams[1],amount) (contracts/core/InfinityExchange.sol#1012) - _emitTakerEvent(makerOrderHash,msg.sender,makerOrder.signer,makerOrder,execPrice) (contracts/core/InfinityExchange.sol#976) Reentrancy in InfinityStaker.rageQuit() (contracts/staking/InfinityStaker.sol#136-145): External calls: - IERC20(INFINITY_TOKEN).safeTransfer(msg.sender,totalToUser) (contracts/staking/InfinityStaker.sol#141) - IERC20(INFINITY_TOKEN).safeTransfer(INFINITY_TREASURY,penalty) (contracts/staking/InfinityStaker.sol#142) Event emitted after the call(s): - RageQuit(msg.sender,totalToUser,penalty) (contracts/staking/InfinityStaker.sol#144) Reentrancy in InfinityStaker.stake(uint256,Duration) (contracts/staking/InfinityStaker.sol#67-77): External calls: - IERC20(INFINITY_TOKEN).safeTransferFrom(msg.sender,address(this),amount) (contracts/staking/InfinityStaker.sol#74) Event emitted after the call(s): - Staked(msg.sender,amount,duration) (contracts/staking/InfinityStaker.sol#76) Reentrancy in InfinityStaker.unstake(uint256) (contracts/staking/InfinityStaker.sol#116-131): External calls: - IERC20(INFINITY_TOKEN).safeTransfer(msg.sender,amount) (contracts/staking/InfinityStaker.sol#128) Event emitted after the call(s): - UnStaked(msg.sender,amount) (contracts/staking/InfinityStaker.sol#130)

Recommendation

Apply the check-effects-interactions pattern.


Calls inside a loop

Information : Calls inside a loop

Instances include :

InfinityExchange.matchOneToOneOrders(OrderTypes.MakerOrder[],OrderTypes.MakerOrder[]) (contracts/core/InfinityExchange.sol#132-169) has external calls inside a loop: (canExec,execPrice) = IComplication(makerOrders1[i].execParams[0]).canExecMatchOneToOne(makerOrders1[i],makerOrders2[i]) (contracts/core/InfinityExchange.sol#151-154) SignatureChecker.verify(bytes32,address,bytes32,bytes32,uint8,bytes32) (contracts/libs/SignatureChecker.sol#51-69) has external calls inside a loop: IERC1271(signer).isValidSignature(digest,abi.encodePacked(r,s,v)) == 0x1626ba7e (contracts/libs/SignatureChecker.sol#65) InfinityExchange._transferNFTs(address,address,OrderTypes.OrderItem) (contracts/core/InfinityExchange.sol#1062-1072) has external calls inside a loop: IERC165(item.collection).supportsInterface(0x80ac58cd) (contracts/core/InfinityExchange.sol#1067) InfinityExchange._transferERC721s(address,address,OrderTypes.OrderItem) (contracts/core/InfinityExchange.sol#1080-1092) has external calls inside a loop: IERC721(item.collection).safeTransferFrom(from,to,item.tokens[i].tokenId) (contracts/core/InfinityExchange.sol#1087) InfinityExchange._transferNFTs(address,address,OrderTypes.OrderItem) (contracts/core/InfinityExchange.sol#1062-1072) has external calls inside a loop: IERC165(item.collection).supportsInterface(0xd9b67a26) (contracts/core/InfinityExchange.sol#1069) InfinityExchange._transferERC1155s(address,address,OrderTypes.OrderItem) (contracts/core/InfinityExchange.sol#1101-1117) has external calls inside a loop: IERC1155(item.collection).safeBatchTransferFrom(from,to,tokenIdsArr,numTokensPerTokenIdArr,0x0) (contracts/core/InfinityExchange.sol#1116) Address.functionCallWithValue(address,bytes,uint256,string) (node_modules/@openzeppelin/contracts/utils/Address.sol#128-139) has external calls inside a loop: (success,returndata) = target.call{value: value}(data) (node_modules/@openzeppelin/contracts/utils/Address.sol#137) InfinityExchange.matchOrders(OrderTypes.MakerOrder[],OrderTypes.MakerOrder[],OrderTypes.OrderItem[][]) (contracts/core/InfinityExchange.sol#256-294) has external calls inside a loop: (executionValid,execPrice) = IComplication(sells[i].execParams[0]).canExecMatchOrder(sells[i],buys[i],constructs[i]) (contracts/core/InfinityExchange.sol#274-278) InfinityExchange._transferFees(address,address,uint256,address) (contracts/core/InfinityExchange.sol#1128-1148) has external calls inside a loop: (sent) = seller.call{value: remainingAmount}() (contracts/core/InfinityExchange.sol#1140) InfinityExchange._takeOrders(OrderTypes.MakerOrder,OrderTypes.OrderItem[],uint256) (contracts/core/InfinityExchange.sol#941-951) has external calls inside a loop: executionValid = IComplication(makerOrder.execParams[0]).canExecTakeOrder(makerOrder,takerItems) (contracts/core/InfinityExchange.sol#948)

Recommendation

Favor pull over push strategy for external calls.


Missing zero address validation

Missing zero address validation

Instances include :

InfinityExchange.constructor(address,address)._WETH (contracts/core/InfinityExchange.sol#104) lacks a zero-check on : - WETH = _WETH (contracts/core/InfinityExchange.sol#115) InfinityExchange.constructor(address,address)._matchExecutor (contracts/core/InfinityExchange.sol#104) lacks a zero-check on : - MATCH_EXECUTOR = _matchExecutor (contracts/core/InfinityExchange.sol#116) InfinityExchange.rescueETH(address).destination (contracts/core/InfinityExchange.sol#1229) lacks a zero-check on : - (sent) = destination.call{value: msg.value}() (contracts/core/InfinityExchange.sol#1230) InfinityExchange.updateMatchExecutor(address)._matchExecutor (contracts/core/InfinityExchange.sol#1255) lacks a zero-check on : - MATCH_EXECUTOR = _matchExecutor (contracts/core/InfinityExchange.sol#1256) InfinityStaker.constructor(address,address)._tokenAddress (contracts/staking/InfinityStaker.sol#49) lacks a zero-check on : - INFINITY_TOKEN = _tokenAddress (contracts/staking/InfinityStaker.sol#50) InfinityStaker.constructor(address,address)._infinityTreasury (contracts/staking/InfinityStaker.sol#49) lacks a zero-check on : - INFINITY_TREASURY = _infinityTreasury (contracts/staking/InfinityStaker.sol#51) InfinityStaker.rescueETH(address).destination (contracts/staking/InfinityStaker.sol#345) lacks a zero-check on : - (sent) = destination.call{value: msg.value}() (contracts/staking/InfinityStaker.sol#346) InfinityStaker.updateInfinityTreasury(address)._infinityTreasury (contracts/staking/InfinityStaker.sol#375) lacks a zero-check on : - INFINITY_TREASURY = _infinityTreasury (contracts/staking/InfinityStaker.sol#376)

Recommendation

Check that the address is not zero.


Missing events arithmetic

Information : Missing events arithmetic

Instances include :

InfinityStaker.updateStakeLevelThreshold(StakeLevel,uint16) (contracts/staking/InfinityStaker.sol#351-361) should emit an event for: - BRONZE_STAKE_THRESHOLD = threshold (contracts/staking/InfinityStaker.sol#353) - SILVER_STAKE_THRESHOLD = threshold (contracts/staking/InfinityStaker.sol#355) - GOLD_STAKE_THRESHOLD = threshold (contracts/staking/InfinityStaker.sol#357) - PLATINUM_STAKE_THRESHOLD = threshold (contracts/staking/InfinityStaker.sol#359) InfinityStaker.updatePenalties(uint16,uint16,uint16) (contracts/staking/InfinityStaker.sol#364-372) should emit an event for: - THREE_MONTH_PENALTY = threeMonthPenalty (contracts/staking/InfinityStaker.sol#369) - SIX_MONTH_PENALTY = sixMonthPenalty (contracts/staking/InfinityStaker.sol#370) - TWELVE_MONTH_PENALTY = twelveMonthPenalty (contracts/staking/InfinityStaker.sol#371)

Recommendation

Emit an event for critical parameter changes.


Unused return

Information : Unused return

Instances include :

InfinityExchange.addCurrency(address) (contracts/core/InfinityExchange.sol#1235-1237) ignores return value by _currencies.add(_currency) (contracts/core/InfinityExchange.sol#1236) InfinityExchange.addComplication(address) (contracts/core/InfinityExchange.sol#1240-1242) ignores return value by _complications.add(_complication) (contracts/core/InfinityExchange.sol#1241) InfinityExchange.removeCurrency(address) (contracts/core/InfinityExchange.sol#1245-1247) ignores return value by _currencies.remove(_currency) (contracts/core/InfinityExchange.sol#1246) InfinityExchange.removeComplication(address) (contracts/core/InfinityExchange.sol#1250-1252) ignores return value by _complications.remove(_complication) (contracts/core/InfinityExchange.sol#1251) TimelockConfig.confirmChange(bytes32) (contracts/token/TimelockConfig.sol#50-62) ignores return value by _configSet.add(configId) (contracts/token/TimelockConfig.sol#55) TimelockConfig.confirmChange(bytes32) (contracts/token/TimelockConfig.sol#50-62) ignores return value by _pendingSet.remove(configId) (contracts/token/TimelockConfig.sol#58) TimelockConfig._setRawConfig(bytes32,uint256) (contracts/token/TimelockConfig.sol#66-72) ignores return value by _configSet.add(configId) (contracts/token/TimelockConfig.sol#67)

Recommendation

Ensure that all the return values of the function calls are used.


Tautology or contradiction

Information : Tautology or contradiction

Instances include :

InfinityStaker.getRageQuitAmounts(address) (contracts/staking/InfinityStaker.sol#181-203) contains a tautology or contradiction: - require(bool,string)(totalStaked >= 0,nothing staked to rage quit) (contracts/staking/InfinityStaker.sol#193)

Recommendation

Fix the incorrect comparison by changing the value type or the comparison.


Divide before multiply

Information : Divide before multiply

Instances include :

InfinityOrderBookComplication._getCurrentPrice(OrderTypes.MakerOrder) (contracts/core/InfinityOrderBookComplication.sol#330-342) performs a multiplication on the result of a division: -priceDiff = (priceDiff * portionBps) / PRECISION (contracts/core/InfinityOrderBookComplication.sol#340) -portionBps = ((elapsedTime * PRECISION) / duration) (contracts/core/InfinityOrderBookComplication.sol#339) InfinityToken.advanceEpoch() (contracts/token/InfinityToken.sol#60-82) performs a multiplication on the result of a division: -epochsPassedSinceLastAdvance = (block.timestamp - previousEpochTimestamp) / getEpochDuration() (contracts/token/InfinityToken.sol#65) -supplyToMint = getInflation() * epochsPassedSinceLastAdvance (contracts/token/InfinityToken.sol#76) -epochsPassedSinceLastAdvance = epochsPassedSinceLastAdvance (contracts/token/InfinityToken.sol#67-69)

Recommendation

Consider ordering multiplication before division.


Use != 0 instead of > 0 when comparing unsigned integers

!= 0 will do the same as > 0 for unsigned integers, but != 0 costs less gas compared to > 0 for unsigned integers in require statements with the optimizer enabled.

Instances include :

core/InfinityExchange.sol:392: require(numNonces > 0, 'cannot be empty');

Recommendation

It is recommended to replace > 0 with != 0, as they do the same thing for unsigned integers, and '!= 0' costs less gas compared to > 0 in require statements with the optimizer enabled, also enable the optimizer.

For example :

core/InfinityExchange.sol:392: require(numNonces != 0, 'cannot be empty');

Don't explicitly initialize variables with the default value

Uninitialized variables are assigned with the default value of their type, initializing a variable with its default value costs unnecessary gas.

Instances include :

core/InfinityExchange.sol:148: for (uint256 i = 0; i < numMakerOrders; ) { core/InfinityExchange.sol:200: for (uint256 i = 0; i < ordersLength; ) { core/InfinityExchange.sol:219: for (uint256 i = 0; i < ordersLength; ) { core/InfinityExchange.sol:272: for (uint256 i = 0; i < numSells; ) { core/InfinityExchange.sol:308: for (uint256 i = 0; i < numMakerOrders; ) { core/InfinityExchange.sol:349: for (uint256 i = 0; i < ordersLength; ) { core/InfinityExchange.sol:393: for (uint256 i = 0; i < numNonces; ) { core/InfinityExchange.sol:1048: for (uint256 i = 0; i < numNfts; ) { core/InfinityExchange.sol:1086: for (uint256 i = 0; i < numTokens; ) { core/InfinityExchange.sol:1109: for (uint256 i = 0; i < numNfts; ) { core/InfinityExchange.sol:1190: for (uint256 i = 0; i < numNfts; ) { core/InfinityExchange.sol:1206: for (uint256 i = 0; i < numTokens; ) { core/InfinityOrderBookComplication.sol:76: for (uint256 i = 0; i < ordersLength; ) { core/InfinityOrderBookComplication.sol:82: for (uint256 j = 0; j < nftsLength; ) { core/InfinityOrderBookComplication.sol:197: uint256 numConstructedItems = 0; core/InfinityOrderBookComplication.sol:199: for (uint256 i = 0; i < nftsLength; ) { core/InfinityOrderBookComplication.sol:214: uint256 numTakerItems = 0; core/InfinityOrderBookComplication.sol:216: for (uint256 i = 0; i < nftsLength; ) { core/InfinityOrderBookComplication.sol:244: uint256 numCollsMatched = 0; core/InfinityOrderBookComplication.sol:246: for (uint256 i = 0; i < order2NftsLength; ) { core/InfinityOrderBookComplication.sol:247: for (uint256 j = 0; j < order1NftsLength; ) { core/InfinityOrderBookComplication.sol:289: uint256 numTokenIdsPerCollMatched = 0; core/InfinityOrderBookComplication.sol:290: for (uint256 k = 0; k < item2TokensLength; ) { core/InfinityOrderBookComplication.sol:291: for (uint256 l = 0; l < item1TokensLength; ) { core/InfinityOrderBookComplication.sol:318: uint256 sum = 0; core/InfinityOrderBookComplication.sol:320: for (uint256 i = 0; i < ordersLength; ) { MockERC721.sol:11: for (uint256 i = 0; i < 100; i++) {

Recommendation

It is recommended to initialize variables without assigning them the default value, for example :

core/InfinityOrderBookComplication.sol:318: uint256 sum;

If possible, use bitwise shift instead of division/multiplication

If the divisor/multiplier x is a power of 2, it can be calculated by shifting log2(x) to the right/left. Division with / cost more gas compared to bitwise shifting.

Instances include :

staking/InfinityStaker.sol:235: (userstakedAmounts[user][Duration.THREE_MONTHS].amount * 2) + staking/InfinityStaker.sol:237: (userstakedAmounts[user][Duration.TWELVE_MONTHS].amount * 4)) / (10**18);

Recommendation

It is recommended to replace / and * with >> and << respectively and divisor/multiplier x to log2(x), for division/multiplication where the divisor/multiplier is a power of 2, for example :

staking/InfinityStaker.sol:235: (userstakedAmounts[user][Duration.THREE_MONTHS].amount << 1) +

If possible, use prefix increment instead of postfix increment

Prefix increment ++i returns the updated value after it's incremented and postfix increment i++ returns the original value then increments it. Prefix increment costs less gas compared to postfix increment.

Instances includes :

MockERC721.sol:11: for (uint256 i = 0; i < 100; i++) { MockERC721.sol:12: _safeMint(msg.sender, numMints++);

Recommendation

It is recommended to use prefix increment instead of postfix one when the return value is not needed, as both of them will give the same result and prefix increment costs less gas.

For example :

MockERC721.sol:11: for (uint256 i = 0; i < 100; ++i) {

Don't use long revert strings

Shortening revert strings to fit in 32 bytes will decrease gas costs for deployment and gas costs when the revert condition has been met.

Instances includes :

core/InfinityExchange.sol:395: require(!isUserOrderNonceExecutedOrCancelled[msg.sender][orderNonces[i]], 'nonce already executed or cancelled'); staking/InfinityStaker.sol:96: require(newDuration > oldDuration, 'new duration must be greater than old duration');

Recommendation

It is recommended to use error code and providing a reference to the error code instead of a long revert string., for example :

// Link to the reference of error codes staking/InfinityStaker.sol:96: require(newDuration > oldDuration, 'ERR');

Public function could be declared external

Public functions that are never called by the contract should be declared external to save gas.

Instances includes :

renounceOwnership() should be declared external: - Ownable.renounceOwnership() (node_modules/@openzeppelin/contracts/access/Ownable.sol#54-56) transferOwnership(address) should be declared external: - Ownable.transferOwnership(address) (node_modules/@openzeppelin/contracts/access/Ownable.sol#62-65) balanceOf(address) should be declared external: - ERC721.balanceOf(address) (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#62-65) name() should be declared external: - ERC721.name() (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#79-81) symbol() should be declared external: - ERC721.symbol() (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#86-88) approve(address,uint256) should be declared external: - ERC721.approve(address,uint256) (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#112-122) setApprovalForAll(address,bool) should be declared external: - ERC721.setApprovalForAll(address,bool) (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#136-138) transferFrom(address,address,uint256) should be declared external: - ERC721.transferFrom(address,address,uint256) (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#150-159) safeTransferFrom(address,address,uint256) should be declared external: - ERC721.safeTransferFrom(address,address,uint256) (node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol#164-170) getUserTotalStaked(address) should be declared external: - InfinityStaker.getUserTotalStaked(address) (contracts/staking/InfinityStaker.sol#154-160) getUserTotalVested(address) should be declared external: - InfinityStaker.getUserTotalVested(address) (contracts/staking/InfinityStaker.sol#167-173)

Recommendation

Use the external attribute for functions never called from the contract.


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