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
Rank: 95/99
Findings: 1
Award: $31.25
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0v3rf10w, 0x1f8b, 0x29A, 0xAsm0d3us, 0xDjango, 0xKitsune, 0xNazgul, 0xf15ers, 0xkatana, 0xkowloon, BowTiedWardens, Chom, ElKu, FSchmoede, Funen, GimelSec, Kaiziron, Kenshin, Lambda, MadWookie, MiloTruck, PPrieditis, Picodes, PwnedNoMore, StErMi, Tadashi, TerrierLover, TomJ, Tomio, Wayne, Waze, _Adam, antonttc, apostle0x01, asutorufos, c3phas, codexploder, defsec, delfin454000, fatherOfBlocks, hake, hansfriese, hyh, joestakey, k, kenta, oyc_109, peritoflores, reassor, rfa, robee, sach1r0, simon135, slywaters, zer0dot
31.2475 USDC - $31.25
Uninitialized variables by default contain a value equivalent to 0: uint
s are initialized to 0; bool
s to false; address
es 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;
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) {
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');
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');