Infinity NFT Marketplace contest - slywaters'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: 95/99

Findings: 1

Award: $31.25

🌟 Selected for report: 0

🚀 Solo Findings: 0

Gas Report

Variables do not need to be initialized with 'empty' values such as 0, false, or address(0)

Uninitialized variables by default contain a value equivalent to 0: uints are initialized to 0; bools to false; addresses to address(0).

Explicitly assigning these values to variables when they are declared increases gas costs while providing no funciton.

e.g. change this code:

uint256 var = 0;

to

uint256 var;

For more information, please consult the following resources:

Tips and Tricks to Save Gas and Reduce Bytecode Size

The following lines of code are affected:

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

"calldata" can be used instead of "memory" to reduce gas costs

Both memory and calldata allow a developer to manage variables within the scope of a function. memory is mutable which makes it a more flexible tool; however, it costs additional gas when compared with calldata. calldata is non-modifiable but cheaper. Therefore it is recommended to use calldata for function parameters when they will not be modified.

For more information, see the following resources: Solidity Documentation recommending the use of calldata

Solidity — Storage vs Memory vs Calldata

The following function call can be changed to use calldata instead of memory:

2022-06-infinity/contracts/token/TimelockConfig.sol:76: function calculateConfigId(string memory name) external pure returns (bytes32 configId) {

Use strict less-than/greather-than comparisons rather than less-than-or-equal/greater-than-or-equal

When compiled, Solidity code using the >= or <= comparison operators in fact executes two separate checks: one for 'is-equal-to' and a second for 'is-greater-than/is-less-than'. By contrast, using > or < performs only one check. Therefore code that is written to use strict comparison operators is more gas-efficient.

If this change is applied, be sure to update the relevant variables being evaluated. For clarity, it is also advised to rename the variables to make this change explicit, e.g. renaming a variable from MINIMUM to MINIMUM_PLUS_ONE.

The following lines are affected:

2022-06-infinity/contracts/core/InfinityExchange.sol:311: bool isTimeValid = makerOrders[i].constraints[3] <= block.timestamp && 2022-06-infinity/contracts/core/InfinityExchange.sol:312: makerOrders[i].constraints[4] >= block.timestamp; 2022-06-infinity/contracts/core/InfinityExchange.sol:326: require(msg.value >= totalPrice, 'invalid total price'); 2022-06-infinity/contracts/core/InfinityExchange.sol:362: require(msg.value >= totalPrice, 'invalid total price'); 2022-06-infinity/contracts/core/InfinityExchange.sol:394: require(orderNonces[i] >= userMinOrderNonce[msg.sender], 'nonce too low'); 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:102: makerOrder.constraints[3] <= block.timestamp && 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:103: makerOrder.constraints[4] >= block.timestamp; 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:110: _isPriceValid = sumCurrentOrderPrices >= currentMakerOrderPrice; 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:112: _isPriceValid = sumCurrentOrderPrices <= currentMakerOrderPrice; 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:160: return (makerOrder.constraints[3] <= block.timestamp && 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:161: makerOrder.constraints[4] >= block.timestamp && 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:175: sell.constraints[3] <= block.timestamp && 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:176: sell.constraints[4] >= block.timestamp && 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:177: buy.constraints[3] <= block.timestamp && 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:178: buy.constraints[4] >= block.timestamp; 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:188: return (currentBuyPrice >= currentSellPrice, currentSellPrice); 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:205: return numConstructedItems >= buy.constraints[0] && buy.constraints[0] <= sell.constraints[0]; 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:38: bool _isTimeValid = makerOrder2.constraints[3] <= block.timestamp && 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:39: makerOrder2.constraints[4] >= block.timestamp && 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:40: makerOrder1.constraints[3] <= block.timestamp && 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:41: makerOrder1.constraints[4] >= block.timestamp; 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:47: _isPriceValid = makerOrder2Price >= makerOrder1Price; 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:50: _isPriceValid = makerOrder1Price >= makerOrder2Price; 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:91: manyMakerOrders[i].constraints[3] <= block.timestamp && 2022-06-infinity/contracts/core/InfinityOrderBookComplication.sol:92: manyMakerOrders[i].constraints[4] >= block.timestamp; 2022-06-infinity/contracts/libs/SignatureChecker.sol:28: uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, 2022-06-infinity/contracts/staking/InfinityStaker.sol:123: require(totalVested >= amount, 'insufficient balance to unstake'); 2022-06-infinity/contracts/staking/InfinityStaker.sol:193: require(totalStaked >= 0, 'nothing staked to rage quit'); 2022-06-infinity/contracts/staking/InfinityStaker.sol:213: if (totalPower <= BRONZE_STAKE_THRESHOLD) { 2022-06-infinity/contracts/staking/InfinityStaker.sol:215: } else if (totalPower > BRONZE_STAKE_THRESHOLD && totalPower <= SILVER_STAKE_THRESHOLD) { 2022-06-infinity/contracts/staking/InfinityStaker.sol:217: } else if (totalPower > SILVER_STAKE_THRESHOLD && totalPower <= GOLD_STAKE_THRESHOLD) { 2022-06-infinity/contracts/staking/InfinityStaker.sol:219: } else if (totalPower > GOLD_STAKE_THRESHOLD && totalPower <= PLATINUM_STAKE_THRESHOLD) { 2022-06-infinity/contracts/staking/InfinityStaker.sol:270: return secondsSinceStake >= durationInSeconds ? amount : 0; 2022-06-infinity/contracts/staking/InfinityStaker.sol:69: require(IERC20(INFINITY_TOKEN).balanceOf(msg.sender) >= amount, 'insufficient balance to stake'); 2022-06-infinity/contracts/staking/InfinityStaker.sol:93: userstakedAmounts[msg.sender][oldDuration].amount >= amount, 2022-06-infinity/contracts/token/InfinityToken.sol:62: require(block.timestamp >= currentEpochTimestamp + getCliff(), 'cliff not passed'); 2022-06-infinity/contracts/token/InfinityToken.sol:63: require(block.timestamp >= previousEpochTimestamp + getEpochDuration(), 'not ready to advance'); 2022-06-infinity/contracts/token/TimelockConfig.sol:52: require(block.timestamp >= _pending[configId].timestamp + _config[TIMELOCK], 'too early');

Split require() calls using && into separate statements

Using && operations within require() statements increases gas costs. Separate these conditions into separate require() calls.

The following require() statements should be refactored:

2022-06-infinity/contracts/core/InfinityExchange.sol:264: require(numSells == buys.length && numSells == constructs.length, 'mismatched lengths'); 2022-06-infinity/contracts/core/InfinityExchange.sol:949: require(makerOrderValid && executionValid, 'order not verified');
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